xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/linker.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2010 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker  * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker /**
25*61046927SAndroid Build Coastguard Worker  * \file linker.cpp
26*61046927SAndroid Build Coastguard Worker  * GLSL linker implementation
27*61046927SAndroid Build Coastguard Worker  *
28*61046927SAndroid Build Coastguard Worker  * Given a set of shaders that are to be linked to generate a final program,
29*61046927SAndroid Build Coastguard Worker  * there are three distinct stages.
30*61046927SAndroid Build Coastguard Worker  *
31*61046927SAndroid Build Coastguard Worker  * In the first stage shaders are partitioned into groups based on the shader
32*61046927SAndroid Build Coastguard Worker  * type.  All shaders of a particular type (e.g., vertex shaders) are linked
33*61046927SAndroid Build Coastguard Worker  * together.
34*61046927SAndroid Build Coastguard Worker  *
35*61046927SAndroid Build Coastguard Worker  *   - Undefined references in each shader are resolve to definitions in
36*61046927SAndroid Build Coastguard Worker  *     another shader.
37*61046927SAndroid Build Coastguard Worker  *   - Types and qualifiers of uniforms, outputs, and global variables defined
38*61046927SAndroid Build Coastguard Worker  *     in multiple shaders with the same name are verified to be the same.
39*61046927SAndroid Build Coastguard Worker  *   - Initializers for uniforms and global variables defined
40*61046927SAndroid Build Coastguard Worker  *     in multiple shaders with the same name are verified to be the same.
41*61046927SAndroid Build Coastguard Worker  *
42*61046927SAndroid Build Coastguard Worker  * The result, in the terminology of the GLSL spec, is a set of shader
43*61046927SAndroid Build Coastguard Worker  * executables for each processing unit.
44*61046927SAndroid Build Coastguard Worker  *
45*61046927SAndroid Build Coastguard Worker  * After the first stage is complete, a series of semantic checks are performed
46*61046927SAndroid Build Coastguard Worker  * on each of the shader executables.
47*61046927SAndroid Build Coastguard Worker  *
48*61046927SAndroid Build Coastguard Worker  *   - Each shader executable must define a \c main function.
49*61046927SAndroid Build Coastguard Worker  *   - Each vertex shader executable must write to \c gl_Position.
50*61046927SAndroid Build Coastguard Worker  *   - Each fragment shader executable must write to either \c gl_FragData or
51*61046927SAndroid Build Coastguard Worker  *     \c gl_FragColor.
52*61046927SAndroid Build Coastguard Worker  *
53*61046927SAndroid Build Coastguard Worker  * In the final stage individual shader executables are linked to create a
54*61046927SAndroid Build Coastguard Worker  * complete exectuable.
55*61046927SAndroid Build Coastguard Worker  *
56*61046927SAndroid Build Coastguard Worker  *   - Types of uniforms defined in multiple shader stages with the same name
57*61046927SAndroid Build Coastguard Worker  *     are verified to be the same.
58*61046927SAndroid Build Coastguard Worker  *   - Initializers for uniforms defined in multiple shader stages with the
59*61046927SAndroid Build Coastguard Worker  *     same name are verified to be the same.
60*61046927SAndroid Build Coastguard Worker  *   - Types and qualifiers of outputs defined in one stage are verified to
61*61046927SAndroid Build Coastguard Worker  *     be the same as the types and qualifiers of inputs defined with the same
62*61046927SAndroid Build Coastguard Worker  *     name in a later stage.
63*61046927SAndroid Build Coastguard Worker  *
64*61046927SAndroid Build Coastguard Worker  * \author Ian Romanick <[email protected]>
65*61046927SAndroid Build Coastguard Worker  */
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker #include <ctype.h>
68*61046927SAndroid Build Coastguard Worker #include "util/strndup.h"
69*61046927SAndroid Build Coastguard Worker #include "glsl_symbol_table.h"
70*61046927SAndroid Build Coastguard Worker #include "glsl_parser_extras.h"
71*61046927SAndroid Build Coastguard Worker #include "ir.h"
72*61046927SAndroid Build Coastguard Worker #include "nir.h"
73*61046927SAndroid Build Coastguard Worker #include "program.h"
74*61046927SAndroid Build Coastguard Worker #include "program/prog_instruction.h"
75*61046927SAndroid Build Coastguard Worker #include "program/program.h"
76*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
77*61046927SAndroid Build Coastguard Worker #include "util/set.h"
78*61046927SAndroid Build Coastguard Worker #include "string_to_uint_map.h"
79*61046927SAndroid Build Coastguard Worker #include "linker.h"
80*61046927SAndroid Build Coastguard Worker #include "linker_util.h"
81*61046927SAndroid Build Coastguard Worker #include "ir_optimization.h"
82*61046927SAndroid Build Coastguard Worker #include "ir_rvalue_visitor.h"
83*61046927SAndroid Build Coastguard Worker #include "ir_uniform.h"
84*61046927SAndroid Build Coastguard Worker #include "builtin_functions.h"
85*61046927SAndroid Build Coastguard Worker #include "shader_cache.h"
86*61046927SAndroid Build Coastguard Worker #include "util/u_string.h"
87*61046927SAndroid Build Coastguard Worker #include "util/u_math.h"
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker #include "main/shaderobj.h"
91*61046927SAndroid Build Coastguard Worker #include "main/enums.h"
92*61046927SAndroid Build Coastguard Worker #include "main/mtypes.h"
93*61046927SAndroid Build Coastguard Worker #include "main/context.h"
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker namespace {
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker /**
99*61046927SAndroid Build Coastguard Worker  * A visitor helper that provides methods for updating the types of
100*61046927SAndroid Build Coastguard Worker  * ir_dereferences.  Classes that update variable types (say, updating
101*61046927SAndroid Build Coastguard Worker  * array sizes) will want to use this so that dereference types stay in sync.
102*61046927SAndroid Build Coastguard Worker  */
103*61046927SAndroid Build Coastguard Worker class deref_type_updater : public ir_hierarchical_visitor {
104*61046927SAndroid Build Coastguard Worker public:
visit(ir_dereference_variable * ir)105*61046927SAndroid Build Coastguard Worker    virtual ir_visitor_status visit(ir_dereference_variable *ir)
106*61046927SAndroid Build Coastguard Worker    {
107*61046927SAndroid Build Coastguard Worker       ir->type = ir->var->type;
108*61046927SAndroid Build Coastguard Worker       return visit_continue;
109*61046927SAndroid Build Coastguard Worker    }
110*61046927SAndroid Build Coastguard Worker 
visit_leave(ir_dereference_array * ir)111*61046927SAndroid Build Coastguard Worker    virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
112*61046927SAndroid Build Coastguard Worker    {
113*61046927SAndroid Build Coastguard Worker       const glsl_type *const vt = ir->array->type;
114*61046927SAndroid Build Coastguard Worker       if (glsl_type_is_array(vt))
115*61046927SAndroid Build Coastguard Worker          ir->type = vt->fields.array;
116*61046927SAndroid Build Coastguard Worker       return visit_continue;
117*61046927SAndroid Build Coastguard Worker    }
118*61046927SAndroid Build Coastguard Worker 
visit_leave(ir_dereference_record * ir)119*61046927SAndroid Build Coastguard Worker    virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
120*61046927SAndroid Build Coastguard Worker    {
121*61046927SAndroid Build Coastguard Worker       ir->type = ir->record->type->fields.structure[ir->field_idx].type;
122*61046927SAndroid Build Coastguard Worker       return visit_continue;
123*61046927SAndroid Build Coastguard Worker    }
124*61046927SAndroid Build Coastguard Worker };
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker class array_length_to_const_visitor : public ir_rvalue_visitor {
128*61046927SAndroid Build Coastguard Worker public:
array_length_to_const_visitor()129*61046927SAndroid Build Coastguard Worker    array_length_to_const_visitor()
130*61046927SAndroid Build Coastguard Worker    {
131*61046927SAndroid Build Coastguard Worker       this->progress = false;
132*61046927SAndroid Build Coastguard Worker    }
133*61046927SAndroid Build Coastguard Worker 
~array_length_to_const_visitor()134*61046927SAndroid Build Coastguard Worker    virtual ~array_length_to_const_visitor()
135*61046927SAndroid Build Coastguard Worker    {
136*61046927SAndroid Build Coastguard Worker       /* empty */
137*61046927SAndroid Build Coastguard Worker    }
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    bool progress;
140*61046927SAndroid Build Coastguard Worker 
handle_rvalue(ir_rvalue ** rvalue)141*61046927SAndroid Build Coastguard Worker    virtual void handle_rvalue(ir_rvalue **rvalue)
142*61046927SAndroid Build Coastguard Worker    {
143*61046927SAndroid Build Coastguard Worker       if (*rvalue == NULL || (*rvalue)->ir_type != ir_type_expression)
144*61046927SAndroid Build Coastguard Worker          return;
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker       ir_expression *expr = (*rvalue)->as_expression();
147*61046927SAndroid Build Coastguard Worker       if (expr) {
148*61046927SAndroid Build Coastguard Worker          if (expr->operation == ir_unop_implicitly_sized_array_length) {
149*61046927SAndroid Build Coastguard Worker             assert(!glsl_type_is_unsized_array(expr->operands[0]->type));
150*61046927SAndroid Build Coastguard Worker             ir_constant *constant = new(expr)
151*61046927SAndroid Build Coastguard Worker                ir_constant(glsl_array_size(expr->operands[0]->type));
152*61046927SAndroid Build Coastguard Worker             if (constant) {
153*61046927SAndroid Build Coastguard Worker                *rvalue = constant;
154*61046927SAndroid Build Coastguard Worker             }
155*61046927SAndroid Build Coastguard Worker          }
156*61046927SAndroid Build Coastguard Worker       }
157*61046927SAndroid Build Coastguard Worker    }
158*61046927SAndroid Build Coastguard Worker };
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker } /* anonymous namespace */
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker void
linker_error(gl_shader_program * prog,const char * fmt,...)163*61046927SAndroid Build Coastguard Worker linker_error(gl_shader_program *prog, const char *fmt, ...)
164*61046927SAndroid Build Coastguard Worker {
165*61046927SAndroid Build Coastguard Worker    va_list ap;
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    ralloc_strcat(&prog->data->InfoLog, "error: ");
168*61046927SAndroid Build Coastguard Worker    va_start(ap, fmt);
169*61046927SAndroid Build Coastguard Worker    ralloc_vasprintf_append(&prog->data->InfoLog, fmt, ap);
170*61046927SAndroid Build Coastguard Worker    va_end(ap);
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    prog->data->LinkStatus = LINKING_FAILURE;
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker void
linker_warning(gl_shader_program * prog,const char * fmt,...)177*61046927SAndroid Build Coastguard Worker linker_warning(gl_shader_program *prog, const char *fmt, ...)
178*61046927SAndroid Build Coastguard Worker {
179*61046927SAndroid Build Coastguard Worker    va_list ap;
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    ralloc_strcat(&prog->data->InfoLog, "warning: ");
182*61046927SAndroid Build Coastguard Worker    va_start(ap, fmt);
183*61046927SAndroid Build Coastguard Worker    ralloc_vasprintf_append(&prog->data->InfoLog, fmt, ap);
184*61046927SAndroid Build Coastguard Worker    va_end(ap);
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker bool
validate_intrastage_arrays(struct gl_shader_program * prog,ir_variable * const var,ir_variable * const existing,bool match_precision)189*61046927SAndroid Build Coastguard Worker validate_intrastage_arrays(struct gl_shader_program *prog,
190*61046927SAndroid Build Coastguard Worker                            ir_variable *const var,
191*61046927SAndroid Build Coastguard Worker                            ir_variable *const existing,
192*61046927SAndroid Build Coastguard Worker                            bool match_precision)
193*61046927SAndroid Build Coastguard Worker {
194*61046927SAndroid Build Coastguard Worker    /* Consider the types to be "the same" if both types are arrays
195*61046927SAndroid Build Coastguard Worker     * of the same type and one of the arrays is implicitly sized.
196*61046927SAndroid Build Coastguard Worker     * In addition, set the type of the linked variable to the
197*61046927SAndroid Build Coastguard Worker     * explicitly sized array.
198*61046927SAndroid Build Coastguard Worker     */
199*61046927SAndroid Build Coastguard Worker    if (glsl_type_is_array(var->type) && glsl_type_is_array(existing->type)) {
200*61046927SAndroid Build Coastguard Worker       const glsl_type *no_array_var = var->type->fields.array;
201*61046927SAndroid Build Coastguard Worker       const glsl_type *no_array_existing = existing->type->fields.array;
202*61046927SAndroid Build Coastguard Worker       bool type_matches;
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker       type_matches = (match_precision ?
205*61046927SAndroid Build Coastguard Worker                       no_array_var == no_array_existing :
206*61046927SAndroid Build Coastguard Worker                       glsl_type_compare_no_precision(no_array_var, no_array_existing));
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker       if (type_matches &&
209*61046927SAndroid Build Coastguard Worker           ((var->type->length == 0)|| (existing->type->length == 0))) {
210*61046927SAndroid Build Coastguard Worker          if (var->type->length != 0) {
211*61046927SAndroid Build Coastguard Worker             if ((int)var->type->length <= existing->data.max_array_access) {
212*61046927SAndroid Build Coastguard Worker                linker_error(prog, "%s `%s' declared as type "
213*61046927SAndroid Build Coastguard Worker                            "`%s' but outermost dimension has an index"
214*61046927SAndroid Build Coastguard Worker                            " of `%i'\n",
215*61046927SAndroid Build Coastguard Worker                            mode_string(var),
216*61046927SAndroid Build Coastguard Worker                            var->name, glsl_get_type_name(var->type),
217*61046927SAndroid Build Coastguard Worker                            existing->data.max_array_access);
218*61046927SAndroid Build Coastguard Worker             }
219*61046927SAndroid Build Coastguard Worker             existing->type = var->type;
220*61046927SAndroid Build Coastguard Worker             return true;
221*61046927SAndroid Build Coastguard Worker          } else if (existing->type->length != 0) {
222*61046927SAndroid Build Coastguard Worker             if((int)existing->type->length <= var->data.max_array_access &&
223*61046927SAndroid Build Coastguard Worker                !existing->data.from_ssbo_unsized_array) {
224*61046927SAndroid Build Coastguard Worker                linker_error(prog, "%s `%s' declared as type "
225*61046927SAndroid Build Coastguard Worker                            "`%s' but outermost dimension has an index"
226*61046927SAndroid Build Coastguard Worker                            " of `%i'\n",
227*61046927SAndroid Build Coastguard Worker                            mode_string(var),
228*61046927SAndroid Build Coastguard Worker                            var->name, glsl_get_type_name(existing->type),
229*61046927SAndroid Build Coastguard Worker                            var->data.max_array_access);
230*61046927SAndroid Build Coastguard Worker             }
231*61046927SAndroid Build Coastguard Worker             return true;
232*61046927SAndroid Build Coastguard Worker          }
233*61046927SAndroid Build Coastguard Worker       }
234*61046927SAndroid Build Coastguard Worker    }
235*61046927SAndroid Build Coastguard Worker    return false;
236*61046927SAndroid Build Coastguard Worker }
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker /**
240*61046927SAndroid Build Coastguard Worker  * Perform validation of global variables used across multiple shaders
241*61046927SAndroid Build Coastguard Worker  */
242*61046927SAndroid Build Coastguard Worker static void
cross_validate_globals(const struct gl_constants * consts,struct gl_shader_program * prog,struct exec_list * ir,glsl_symbol_table * variables,bool uniforms_only)243*61046927SAndroid Build Coastguard Worker cross_validate_globals(const struct gl_constants *consts,
244*61046927SAndroid Build Coastguard Worker                        struct gl_shader_program *prog,
245*61046927SAndroid Build Coastguard Worker                        struct exec_list *ir, glsl_symbol_table *variables,
246*61046927SAndroid Build Coastguard Worker                        bool uniforms_only)
247*61046927SAndroid Build Coastguard Worker {
248*61046927SAndroid Build Coastguard Worker    foreach_in_list(ir_instruction, node, ir) {
249*61046927SAndroid Build Coastguard Worker       ir_variable *const var = node->as_variable();
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker       if (var == NULL)
252*61046927SAndroid Build Coastguard Worker          continue;
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker       if (uniforms_only && (var->data.mode != ir_var_uniform && var->data.mode != ir_var_shader_storage))
255*61046927SAndroid Build Coastguard Worker          continue;
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker       /* don't cross validate subroutine uniforms */
258*61046927SAndroid Build Coastguard Worker       if (glsl_contains_subroutine(var->type))
259*61046927SAndroid Build Coastguard Worker          continue;
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker       /* Don't cross validate interface instances. These are only relevant
262*61046927SAndroid Build Coastguard Worker        * inside a shader. The cross validation is done at the Interface Block
263*61046927SAndroid Build Coastguard Worker        * name level.
264*61046927SAndroid Build Coastguard Worker        */
265*61046927SAndroid Build Coastguard Worker       if (var->is_interface_instance())
266*61046927SAndroid Build Coastguard Worker          continue;
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker       /* Don't cross validate temporaries that are at global scope.  These
269*61046927SAndroid Build Coastguard Worker        * will eventually get pulled into the shaders 'main'.
270*61046927SAndroid Build Coastguard Worker        */
271*61046927SAndroid Build Coastguard Worker       if (var->data.mode == ir_var_temporary)
272*61046927SAndroid Build Coastguard Worker          continue;
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker       /* If a global with this name has already been seen, verify that the
275*61046927SAndroid Build Coastguard Worker        * new instance has the same type.  In addition, if the globals have
276*61046927SAndroid Build Coastguard Worker        * initializers, the values of the initializers must be the same.
277*61046927SAndroid Build Coastguard Worker        */
278*61046927SAndroid Build Coastguard Worker       ir_variable *const existing = variables->get_variable(var->name);
279*61046927SAndroid Build Coastguard Worker       if (existing != NULL) {
280*61046927SAndroid Build Coastguard Worker          /* Check if types match. */
281*61046927SAndroid Build Coastguard Worker          if (var->type != existing->type) {
282*61046927SAndroid Build Coastguard Worker             if (!validate_intrastage_arrays(prog, var, existing)) {
283*61046927SAndroid Build Coastguard Worker                /* If it is an unsized array in a Shader Storage Block,
284*61046927SAndroid Build Coastguard Worker                 * two different shaders can access to different elements.
285*61046927SAndroid Build Coastguard Worker                 * Because of that, they might be converted to different
286*61046927SAndroid Build Coastguard Worker                 * sized arrays, then check that they are compatible but
287*61046927SAndroid Build Coastguard Worker                 * ignore the array size.
288*61046927SAndroid Build Coastguard Worker                 */
289*61046927SAndroid Build Coastguard Worker                if (!(var->data.mode == ir_var_shader_storage &&
290*61046927SAndroid Build Coastguard Worker                      var->data.from_ssbo_unsized_array &&
291*61046927SAndroid Build Coastguard Worker                      existing->data.mode == ir_var_shader_storage &&
292*61046927SAndroid Build Coastguard Worker                      existing->data.from_ssbo_unsized_array &&
293*61046927SAndroid Build Coastguard Worker                      var->type->gl_type == existing->type->gl_type)) {
294*61046927SAndroid Build Coastguard Worker                   linker_error(prog, "%s `%s' declared as type "
295*61046927SAndroid Build Coastguard Worker                                  "`%s' and type `%s'\n",
296*61046927SAndroid Build Coastguard Worker                                  mode_string(var),
297*61046927SAndroid Build Coastguard Worker                                  var->name, glsl_get_type_name(var->type),
298*61046927SAndroid Build Coastguard Worker                                  glsl_get_type_name(existing->type));
299*61046927SAndroid Build Coastguard Worker                   return;
300*61046927SAndroid Build Coastguard Worker                }
301*61046927SAndroid Build Coastguard Worker             }
302*61046927SAndroid Build Coastguard Worker          }
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker          if (var->data.explicit_location) {
305*61046927SAndroid Build Coastguard Worker             if (existing->data.explicit_location
306*61046927SAndroid Build Coastguard Worker                 && (var->data.location != existing->data.location)) {
307*61046927SAndroid Build Coastguard Worker                linker_error(prog, "explicit locations for %s "
308*61046927SAndroid Build Coastguard Worker                             "`%s' have differing values\n",
309*61046927SAndroid Build Coastguard Worker                             mode_string(var), var->name);
310*61046927SAndroid Build Coastguard Worker                return;
311*61046927SAndroid Build Coastguard Worker             }
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker             if (var->data.location_frac != existing->data.location_frac) {
314*61046927SAndroid Build Coastguard Worker                linker_error(prog, "explicit components for %s `%s' have "
315*61046927SAndroid Build Coastguard Worker                             "differing values\n", mode_string(var), var->name);
316*61046927SAndroid Build Coastguard Worker                return;
317*61046927SAndroid Build Coastguard Worker             }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker             existing->data.location = var->data.location;
320*61046927SAndroid Build Coastguard Worker             existing->data.explicit_location = true;
321*61046927SAndroid Build Coastguard Worker          } else {
322*61046927SAndroid Build Coastguard Worker             /* Check if uniform with implicit location was marked explicit
323*61046927SAndroid Build Coastguard Worker              * by earlier shader stage. If so, mark it explicit in this stage
324*61046927SAndroid Build Coastguard Worker              * too to make sure later processing does not treat it as
325*61046927SAndroid Build Coastguard Worker              * implicit one.
326*61046927SAndroid Build Coastguard Worker              */
327*61046927SAndroid Build Coastguard Worker             if (existing->data.explicit_location) {
328*61046927SAndroid Build Coastguard Worker                var->data.location = existing->data.location;
329*61046927SAndroid Build Coastguard Worker                var->data.explicit_location = true;
330*61046927SAndroid Build Coastguard Worker             }
331*61046927SAndroid Build Coastguard Worker          }
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker          /* From the GLSL 4.20 specification:
334*61046927SAndroid Build Coastguard Worker           * "A link error will result if two compilation units in a program
335*61046927SAndroid Build Coastguard Worker           *  specify different integer-constant bindings for the same
336*61046927SAndroid Build Coastguard Worker           *  opaque-uniform name.  However, it is not an error to specify a
337*61046927SAndroid Build Coastguard Worker           *  binding on some but not all declarations for the same name"
338*61046927SAndroid Build Coastguard Worker           */
339*61046927SAndroid Build Coastguard Worker          if (var->data.explicit_binding) {
340*61046927SAndroid Build Coastguard Worker             if (existing->data.explicit_binding &&
341*61046927SAndroid Build Coastguard Worker                 var->data.binding != existing->data.binding) {
342*61046927SAndroid Build Coastguard Worker                linker_error(prog, "explicit bindings for %s "
343*61046927SAndroid Build Coastguard Worker                             "`%s' have differing values\n",
344*61046927SAndroid Build Coastguard Worker                             mode_string(var), var->name);
345*61046927SAndroid Build Coastguard Worker                return;
346*61046927SAndroid Build Coastguard Worker             }
347*61046927SAndroid Build Coastguard Worker 
348*61046927SAndroid Build Coastguard Worker             existing->data.binding = var->data.binding;
349*61046927SAndroid Build Coastguard Worker             existing->data.explicit_binding = true;
350*61046927SAndroid Build Coastguard Worker          }
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker          if (glsl_contains_atomic(var->type) &&
353*61046927SAndroid Build Coastguard Worker              var->data.offset != existing->data.offset) {
354*61046927SAndroid Build Coastguard Worker             linker_error(prog, "offset specifications for %s "
355*61046927SAndroid Build Coastguard Worker                          "`%s' have differing values\n",
356*61046927SAndroid Build Coastguard Worker                          mode_string(var), var->name);
357*61046927SAndroid Build Coastguard Worker             return;
358*61046927SAndroid Build Coastguard Worker          }
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker          /* Validate layout qualifiers for gl_FragDepth.
361*61046927SAndroid Build Coastguard Worker           *
362*61046927SAndroid Build Coastguard Worker           * From the AMD/ARB_conservative_depth specs:
363*61046927SAndroid Build Coastguard Worker           *
364*61046927SAndroid Build Coastguard Worker           *    "If gl_FragDepth is redeclared in any fragment shader in a
365*61046927SAndroid Build Coastguard Worker           *    program, it must be redeclared in all fragment shaders in
366*61046927SAndroid Build Coastguard Worker           *    that program that have static assignments to
367*61046927SAndroid Build Coastguard Worker           *    gl_FragDepth. All redeclarations of gl_FragDepth in all
368*61046927SAndroid Build Coastguard Worker           *    fragment shaders in a single program must have the same set
369*61046927SAndroid Build Coastguard Worker           *    of qualifiers."
370*61046927SAndroid Build Coastguard Worker           */
371*61046927SAndroid Build Coastguard Worker          if (strcmp(var->name, "gl_FragDepth") == 0) {
372*61046927SAndroid Build Coastguard Worker             bool layout_declared = var->data.depth_layout != ir_depth_layout_none;
373*61046927SAndroid Build Coastguard Worker             bool layout_differs =
374*61046927SAndroid Build Coastguard Worker                var->data.depth_layout != existing->data.depth_layout;
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker             if (layout_declared && layout_differs) {
377*61046927SAndroid Build Coastguard Worker                linker_error(prog,
378*61046927SAndroid Build Coastguard Worker                             "All redeclarations of gl_FragDepth in all "
379*61046927SAndroid Build Coastguard Worker                             "fragment shaders in a single program must have "
380*61046927SAndroid Build Coastguard Worker                             "the same set of qualifiers.\n");
381*61046927SAndroid Build Coastguard Worker             }
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker             if (var->data.used && layout_differs) {
384*61046927SAndroid Build Coastguard Worker                linker_error(prog,
385*61046927SAndroid Build Coastguard Worker                             "If gl_FragDepth is redeclared with a layout "
386*61046927SAndroid Build Coastguard Worker                             "qualifier in any fragment shader, it must be "
387*61046927SAndroid Build Coastguard Worker                             "redeclared with the same layout qualifier in "
388*61046927SAndroid Build Coastguard Worker                             "all fragment shaders that have assignments to "
389*61046927SAndroid Build Coastguard Worker                             "gl_FragDepth\n");
390*61046927SAndroid Build Coastguard Worker             }
391*61046927SAndroid Build Coastguard Worker          }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker          /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says:
394*61046927SAndroid Build Coastguard Worker           *
395*61046927SAndroid Build Coastguard Worker           *     "If a shared global has multiple initializers, the
396*61046927SAndroid Build Coastguard Worker           *     initializers must all be constant expressions, and they
397*61046927SAndroid Build Coastguard Worker           *     must all have the same value. Otherwise, a link error will
398*61046927SAndroid Build Coastguard Worker           *     result. (A shared global having only one initializer does
399*61046927SAndroid Build Coastguard Worker           *     not require that initializer to be a constant expression.)"
400*61046927SAndroid Build Coastguard Worker           *
401*61046927SAndroid Build Coastguard Worker           * Previous to 4.20 the GLSL spec simply said that initializers
402*61046927SAndroid Build Coastguard Worker           * must have the same value.  In this case of non-constant
403*61046927SAndroid Build Coastguard Worker           * initializers, this was impossible to determine.  As a result,
404*61046927SAndroid Build Coastguard Worker           * no vendor actually implemented that behavior.  The 4.20
405*61046927SAndroid Build Coastguard Worker           * behavior matches the implemented behavior of at least one other
406*61046927SAndroid Build Coastguard Worker           * vendor, so we'll implement that for all GLSL versions.
407*61046927SAndroid Build Coastguard Worker           * If (at least) one of these constant expressions is implicit,
408*61046927SAndroid Build Coastguard Worker           * because it was added by glsl_zero_init, we skip the verification.
409*61046927SAndroid Build Coastguard Worker           */
410*61046927SAndroid Build Coastguard Worker          if (var->constant_initializer != NULL) {
411*61046927SAndroid Build Coastguard Worker             if (existing->constant_initializer != NULL &&
412*61046927SAndroid Build Coastguard Worker                 !existing->data.is_implicit_initializer &&
413*61046927SAndroid Build Coastguard Worker                 !var->data.is_implicit_initializer) {
414*61046927SAndroid Build Coastguard Worker                if (!var->constant_initializer->has_value(existing->constant_initializer)) {
415*61046927SAndroid Build Coastguard Worker                   linker_error(prog, "initializers for %s "
416*61046927SAndroid Build Coastguard Worker                                "`%s' have differing values\n",
417*61046927SAndroid Build Coastguard Worker                                mode_string(var), var->name);
418*61046927SAndroid Build Coastguard Worker                   return;
419*61046927SAndroid Build Coastguard Worker                }
420*61046927SAndroid Build Coastguard Worker             } else {
421*61046927SAndroid Build Coastguard Worker                /* If the first-seen instance of a particular uniform did
422*61046927SAndroid Build Coastguard Worker                 * not have an initializer but a later instance does,
423*61046927SAndroid Build Coastguard Worker                 * replace the former with the later.
424*61046927SAndroid Build Coastguard Worker                 */
425*61046927SAndroid Build Coastguard Worker                if (!var->data.is_implicit_initializer)
426*61046927SAndroid Build Coastguard Worker                   variables->replace_variable(existing->name, var);
427*61046927SAndroid Build Coastguard Worker             }
428*61046927SAndroid Build Coastguard Worker          }
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker          if (var->data.has_initializer) {
431*61046927SAndroid Build Coastguard Worker             if (existing->data.has_initializer
432*61046927SAndroid Build Coastguard Worker                 && (var->constant_initializer == NULL
433*61046927SAndroid Build Coastguard Worker                     || existing->constant_initializer == NULL)) {
434*61046927SAndroid Build Coastguard Worker                linker_error(prog,
435*61046927SAndroid Build Coastguard Worker                             "shared global variable `%s' has multiple "
436*61046927SAndroid Build Coastguard Worker                             "non-constant initializers.\n",
437*61046927SAndroid Build Coastguard Worker                             var->name);
438*61046927SAndroid Build Coastguard Worker                return;
439*61046927SAndroid Build Coastguard Worker             }
440*61046927SAndroid Build Coastguard Worker          }
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker          if (existing->data.explicit_invariant != var->data.explicit_invariant) {
443*61046927SAndroid Build Coastguard Worker             linker_error(prog, "declarations for %s `%s' have "
444*61046927SAndroid Build Coastguard Worker                          "mismatching invariant qualifiers\n",
445*61046927SAndroid Build Coastguard Worker                          mode_string(var), var->name);
446*61046927SAndroid Build Coastguard Worker             return;
447*61046927SAndroid Build Coastguard Worker          }
448*61046927SAndroid Build Coastguard Worker          if (existing->data.centroid != var->data.centroid) {
449*61046927SAndroid Build Coastguard Worker             linker_error(prog, "declarations for %s `%s' have "
450*61046927SAndroid Build Coastguard Worker                          "mismatching centroid qualifiers\n",
451*61046927SAndroid Build Coastguard Worker                          mode_string(var), var->name);
452*61046927SAndroid Build Coastguard Worker             return;
453*61046927SAndroid Build Coastguard Worker          }
454*61046927SAndroid Build Coastguard Worker          if (existing->data.sample != var->data.sample) {
455*61046927SAndroid Build Coastguard Worker             linker_error(prog, "declarations for %s `%s` have "
456*61046927SAndroid Build Coastguard Worker                          "mismatching sample qualifiers\n",
457*61046927SAndroid Build Coastguard Worker                          mode_string(var), var->name);
458*61046927SAndroid Build Coastguard Worker             return;
459*61046927SAndroid Build Coastguard Worker          }
460*61046927SAndroid Build Coastguard Worker          if (existing->data.image_format != var->data.image_format) {
461*61046927SAndroid Build Coastguard Worker             linker_error(prog, "declarations for %s `%s` have "
462*61046927SAndroid Build Coastguard Worker                          "mismatching image format qualifiers\n",
463*61046927SAndroid Build Coastguard Worker                          mode_string(var), var->name);
464*61046927SAndroid Build Coastguard Worker             return;
465*61046927SAndroid Build Coastguard Worker          }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker          /* Check the precision qualifier matches for uniform variables on
468*61046927SAndroid Build Coastguard Worker           * GLSL ES.
469*61046927SAndroid Build Coastguard Worker           */
470*61046927SAndroid Build Coastguard Worker          if (!consts->AllowGLSLRelaxedES &&
471*61046927SAndroid Build Coastguard Worker              prog->IsES && !var->get_interface_type() &&
472*61046927SAndroid Build Coastguard Worker              existing->data.precision != var->data.precision) {
473*61046927SAndroid Build Coastguard Worker             if ((existing->data.used && var->data.used) ||
474*61046927SAndroid Build Coastguard Worker                 prog->GLSL_Version >= 300) {
475*61046927SAndroid Build Coastguard Worker                linker_error(prog, "declarations for %s `%s` have "
476*61046927SAndroid Build Coastguard Worker                             "mismatching precision qualifiers\n",
477*61046927SAndroid Build Coastguard Worker                             mode_string(var), var->name);
478*61046927SAndroid Build Coastguard Worker                return;
479*61046927SAndroid Build Coastguard Worker             } else {
480*61046927SAndroid Build Coastguard Worker                linker_warning(prog, "declarations for %s `%s` have "
481*61046927SAndroid Build Coastguard Worker                               "mismatching precision qualifiers\n",
482*61046927SAndroid Build Coastguard Worker                               mode_string(var), var->name);
483*61046927SAndroid Build Coastguard Worker             }
484*61046927SAndroid Build Coastguard Worker          }
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker          /* In OpenGL GLSL 3.20 spec, section 4.3.9:
487*61046927SAndroid Build Coastguard Worker           *
488*61046927SAndroid Build Coastguard Worker           *   "It is a link-time error if any particular shader interface
489*61046927SAndroid Build Coastguard Worker           *    contains:
490*61046927SAndroid Build Coastguard Worker           *
491*61046927SAndroid Build Coastguard Worker           *    - two different blocks, each having no instance name, and each
492*61046927SAndroid Build Coastguard Worker           *      having a member of the same name, or
493*61046927SAndroid Build Coastguard Worker           *
494*61046927SAndroid Build Coastguard Worker           *    - a variable outside a block, and a block with no instance name,
495*61046927SAndroid Build Coastguard Worker           *      where the variable has the same name as a member in the block."
496*61046927SAndroid Build Coastguard Worker           */
497*61046927SAndroid Build Coastguard Worker          const glsl_type *var_itype = var->get_interface_type();
498*61046927SAndroid Build Coastguard Worker          const glsl_type *existing_itype = existing->get_interface_type();
499*61046927SAndroid Build Coastguard Worker          if (var_itype != existing_itype) {
500*61046927SAndroid Build Coastguard Worker             if (!var_itype || !existing_itype) {
501*61046927SAndroid Build Coastguard Worker                linker_error(prog, "declarations for %s `%s` are inside block "
502*61046927SAndroid Build Coastguard Worker                             "`%s` and outside a block",
503*61046927SAndroid Build Coastguard Worker                             mode_string(var), var->name,
504*61046927SAndroid Build Coastguard Worker                             glsl_get_type_name(var_itype ? var_itype : existing_itype));
505*61046927SAndroid Build Coastguard Worker                return;
506*61046927SAndroid Build Coastguard Worker             } else if (strcmp(glsl_get_type_name(var_itype), glsl_get_type_name(existing_itype)) != 0) {
507*61046927SAndroid Build Coastguard Worker                linker_error(prog, "declarations for %s `%s` are inside blocks "
508*61046927SAndroid Build Coastguard Worker                             "`%s` and `%s`",
509*61046927SAndroid Build Coastguard Worker                             mode_string(var), var->name,
510*61046927SAndroid Build Coastguard Worker                             glsl_get_type_name(existing_itype),
511*61046927SAndroid Build Coastguard Worker                             glsl_get_type_name(var_itype));
512*61046927SAndroid Build Coastguard Worker                return;
513*61046927SAndroid Build Coastguard Worker             }
514*61046927SAndroid Build Coastguard Worker          }
515*61046927SAndroid Build Coastguard Worker       } else
516*61046927SAndroid Build Coastguard Worker          variables->add_variable(var);
517*61046927SAndroid Build Coastguard Worker    }
518*61046927SAndroid Build Coastguard Worker }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker /**
521*61046927SAndroid Build Coastguard Worker  * Populates a shaders symbol table with all global declarations
522*61046927SAndroid Build Coastguard Worker  */
523*61046927SAndroid Build Coastguard Worker static void
populate_symbol_table(gl_linked_shader * sh,glsl_symbol_table * symbols)524*61046927SAndroid Build Coastguard Worker populate_symbol_table(gl_linked_shader *sh, glsl_symbol_table *symbols)
525*61046927SAndroid Build Coastguard Worker {
526*61046927SAndroid Build Coastguard Worker    sh->symbols = new(sh) glsl_symbol_table;
527*61046927SAndroid Build Coastguard Worker 
528*61046927SAndroid Build Coastguard Worker    _mesa_glsl_copy_symbols_from_table(sh->ir, symbols, sh->symbols);
529*61046927SAndroid Build Coastguard Worker }
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker 
532*61046927SAndroid Build Coastguard Worker /**
533*61046927SAndroid Build Coastguard Worker  * Remap variables referenced in an instruction tree
534*61046927SAndroid Build Coastguard Worker  *
535*61046927SAndroid Build Coastguard Worker  * This is used when instruction trees are cloned from one shader and placed in
536*61046927SAndroid Build Coastguard Worker  * another.  These trees will contain references to \c ir_variable nodes that
537*61046927SAndroid Build Coastguard Worker  * do not exist in the target shader.  This function finds these \c ir_variable
538*61046927SAndroid Build Coastguard Worker  * references and replaces the references with matching variables in the target
539*61046927SAndroid Build Coastguard Worker  * shader.
540*61046927SAndroid Build Coastguard Worker  *
541*61046927SAndroid Build Coastguard Worker  * If there is no matching variable in the target shader, a clone of the
542*61046927SAndroid Build Coastguard Worker  * \c ir_variable is made and added to the target shader.  The new variable is
543*61046927SAndroid Build Coastguard Worker  * added to \b both the instruction stream and the symbol table.
544*61046927SAndroid Build Coastguard Worker  *
545*61046927SAndroid Build Coastguard Worker  * \param inst         IR tree that is to be processed.
546*61046927SAndroid Build Coastguard Worker  * \param symbols      Symbol table containing global scope symbols in the
547*61046927SAndroid Build Coastguard Worker  *                     linked shader.
548*61046927SAndroid Build Coastguard Worker  * \param instructions Instruction stream where new variable declarations
549*61046927SAndroid Build Coastguard Worker  *                     should be added.
550*61046927SAndroid Build Coastguard Worker  */
551*61046927SAndroid Build Coastguard Worker static void
remap_variables(ir_instruction * inst,struct gl_linked_shader * target,hash_table * temps)552*61046927SAndroid Build Coastguard Worker remap_variables(ir_instruction *inst, struct gl_linked_shader *target,
553*61046927SAndroid Build Coastguard Worker                 hash_table *temps)
554*61046927SAndroid Build Coastguard Worker {
555*61046927SAndroid Build Coastguard Worker    class remap_visitor : public ir_hierarchical_visitor {
556*61046927SAndroid Build Coastguard Worker    public:
557*61046927SAndroid Build Coastguard Worker          remap_visitor(struct gl_linked_shader *target, hash_table *temps)
558*61046927SAndroid Build Coastguard Worker       {
559*61046927SAndroid Build Coastguard Worker          this->target = target;
560*61046927SAndroid Build Coastguard Worker          this->symbols = target->symbols;
561*61046927SAndroid Build Coastguard Worker          this->instructions = target->ir;
562*61046927SAndroid Build Coastguard Worker          this->temps = temps;
563*61046927SAndroid Build Coastguard Worker       }
564*61046927SAndroid Build Coastguard Worker 
565*61046927SAndroid Build Coastguard Worker       virtual ir_visitor_status visit(ir_dereference_variable *ir)
566*61046927SAndroid Build Coastguard Worker       {
567*61046927SAndroid Build Coastguard Worker          if (ir->var->data.mode == ir_var_temporary) {
568*61046927SAndroid Build Coastguard Worker             hash_entry *entry = _mesa_hash_table_search(temps, ir->var);
569*61046927SAndroid Build Coastguard Worker             ir_variable *var = entry ? (ir_variable *) entry->data : NULL;
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker             assert(var != NULL);
572*61046927SAndroid Build Coastguard Worker             ir->var = var;
573*61046927SAndroid Build Coastguard Worker             return visit_continue;
574*61046927SAndroid Build Coastguard Worker          }
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker          ir_variable *const existing =
577*61046927SAndroid Build Coastguard Worker             this->symbols->get_variable(ir->var->name);
578*61046927SAndroid Build Coastguard Worker          if (existing != NULL)
579*61046927SAndroid Build Coastguard Worker             ir->var = existing;
580*61046927SAndroid Build Coastguard Worker          else {
581*61046927SAndroid Build Coastguard Worker             ir_variable *copy = ir->var->clone(this->target, NULL);
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker             this->symbols->add_variable(copy);
584*61046927SAndroid Build Coastguard Worker             this->instructions->push_head(copy);
585*61046927SAndroid Build Coastguard Worker             ir->var = copy;
586*61046927SAndroid Build Coastguard Worker          }
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker          return visit_continue;
589*61046927SAndroid Build Coastguard Worker       }
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    private:
592*61046927SAndroid Build Coastguard Worker       struct gl_linked_shader *target;
593*61046927SAndroid Build Coastguard Worker       glsl_symbol_table *symbols;
594*61046927SAndroid Build Coastguard Worker       exec_list *instructions;
595*61046927SAndroid Build Coastguard Worker       hash_table *temps;
596*61046927SAndroid Build Coastguard Worker    };
597*61046927SAndroid Build Coastguard Worker 
598*61046927SAndroid Build Coastguard Worker    remap_visitor v(target, temps);
599*61046927SAndroid Build Coastguard Worker 
600*61046927SAndroid Build Coastguard Worker    inst->accept(&v);
601*61046927SAndroid Build Coastguard Worker }
602*61046927SAndroid Build Coastguard Worker 
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker /**
605*61046927SAndroid Build Coastguard Worker  * Move non-declarations from one instruction stream to another
606*61046927SAndroid Build Coastguard Worker  *
607*61046927SAndroid Build Coastguard Worker  * The intended usage pattern of this function is to pass the pointer to the
608*61046927SAndroid Build Coastguard Worker  * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node
609*61046927SAndroid Build Coastguard Worker  * pointer) for \c last and \c false for \c make_copies on the first
610*61046927SAndroid Build Coastguard Worker  * call.  Successive calls pass the return value of the previous call for
611*61046927SAndroid Build Coastguard Worker  * \c last and \c true for \c make_copies.
612*61046927SAndroid Build Coastguard Worker  *
613*61046927SAndroid Build Coastguard Worker  * \param instructions Source instruction stream
614*61046927SAndroid Build Coastguard Worker  * \param last         Instruction after which new instructions should be
615*61046927SAndroid Build Coastguard Worker  *                     inserted in the target instruction stream
616*61046927SAndroid Build Coastguard Worker  * \param make_copies  Flag selecting whether instructions in \c instructions
617*61046927SAndroid Build Coastguard Worker  *                     should be copied (via \c ir_instruction::clone) into the
618*61046927SAndroid Build Coastguard Worker  *                     target list or moved.
619*61046927SAndroid Build Coastguard Worker  *
620*61046927SAndroid Build Coastguard Worker  * \return
621*61046927SAndroid Build Coastguard Worker  * The new "last" instruction in the target instruction stream.  This pointer
622*61046927SAndroid Build Coastguard Worker  * is suitable for use as the \c last parameter of a later call to this
623*61046927SAndroid Build Coastguard Worker  * function.
624*61046927SAndroid Build Coastguard Worker  */
625*61046927SAndroid Build Coastguard Worker static exec_node *
move_non_declarations(exec_list * instructions,exec_node * last,bool make_copies,gl_linked_shader * target)626*61046927SAndroid Build Coastguard Worker move_non_declarations(exec_list *instructions, exec_node *last,
627*61046927SAndroid Build Coastguard Worker                       bool make_copies, gl_linked_shader *target)
628*61046927SAndroid Build Coastguard Worker {
629*61046927SAndroid Build Coastguard Worker    hash_table *temps = NULL;
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker    if (make_copies)
632*61046927SAndroid Build Coastguard Worker       temps = _mesa_pointer_hash_table_create(NULL);
633*61046927SAndroid Build Coastguard Worker 
634*61046927SAndroid Build Coastguard Worker    foreach_in_list_safe(ir_instruction, inst, instructions) {
635*61046927SAndroid Build Coastguard Worker       if (inst->as_function())
636*61046927SAndroid Build Coastguard Worker          continue;
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker       ir_variable *var = inst->as_variable();
639*61046927SAndroid Build Coastguard Worker       if ((var != NULL) && (var->data.mode != ir_var_temporary))
640*61046927SAndroid Build Coastguard Worker          continue;
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker       assert(inst->as_assignment()
643*61046927SAndroid Build Coastguard Worker              || inst->as_call()
644*61046927SAndroid Build Coastguard Worker              || inst->as_if() /* for initializers with the ?: operator */
645*61046927SAndroid Build Coastguard Worker              || ((var != NULL) && (var->data.mode == ir_var_temporary)));
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker       if (make_copies) {
648*61046927SAndroid Build Coastguard Worker          inst = inst->clone(target, NULL);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker          if (var != NULL)
651*61046927SAndroid Build Coastguard Worker             _mesa_hash_table_insert(temps, var, inst);
652*61046927SAndroid Build Coastguard Worker          else
653*61046927SAndroid Build Coastguard Worker             remap_variables(inst, target, temps);
654*61046927SAndroid Build Coastguard Worker       } else {
655*61046927SAndroid Build Coastguard Worker          inst->remove();
656*61046927SAndroid Build Coastguard Worker       }
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker       last->insert_after(inst);
659*61046927SAndroid Build Coastguard Worker       last = inst;
660*61046927SAndroid Build Coastguard Worker    }
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker    if (make_copies)
663*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_destroy(temps, NULL);
664*61046927SAndroid Build Coastguard Worker 
665*61046927SAndroid Build Coastguard Worker    return last;
666*61046927SAndroid Build Coastguard Worker }
667*61046927SAndroid Build Coastguard Worker 
668*61046927SAndroid Build Coastguard Worker 
669*61046927SAndroid Build Coastguard Worker /**
670*61046927SAndroid Build Coastguard Worker  * This class is only used in link_intrastage_shaders() below but declaring
671*61046927SAndroid Build Coastguard Worker  * it inside that function leads to compiler warnings with some versions of
672*61046927SAndroid Build Coastguard Worker  * gcc.
673*61046927SAndroid Build Coastguard Worker  */
674*61046927SAndroid Build Coastguard Worker class array_sizing_visitor : public deref_type_updater {
675*61046927SAndroid Build Coastguard Worker public:
676*61046927SAndroid Build Coastguard Worker    using deref_type_updater::visit;
677*61046927SAndroid Build Coastguard Worker 
array_sizing_visitor()678*61046927SAndroid Build Coastguard Worker    array_sizing_visitor()
679*61046927SAndroid Build Coastguard Worker       : mem_ctx(ralloc_context(NULL)),
680*61046927SAndroid Build Coastguard Worker         unnamed_interfaces(_mesa_pointer_hash_table_create(NULL))
681*61046927SAndroid Build Coastguard Worker    {
682*61046927SAndroid Build Coastguard Worker    }
683*61046927SAndroid Build Coastguard Worker 
~array_sizing_visitor()684*61046927SAndroid Build Coastguard Worker    ~array_sizing_visitor()
685*61046927SAndroid Build Coastguard Worker    {
686*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_destroy(this->unnamed_interfaces, NULL);
687*61046927SAndroid Build Coastguard Worker       ralloc_free(this->mem_ctx);
688*61046927SAndroid Build Coastguard Worker    }
689*61046927SAndroid Build Coastguard Worker 
690*61046927SAndroid Build Coastguard Worker    array_sizing_visitor(const array_sizing_visitor &) = delete;
691*61046927SAndroid Build Coastguard Worker    array_sizing_visitor & operator=(const array_sizing_visitor &) = delete;
692*61046927SAndroid Build Coastguard Worker 
visit(ir_variable * var)693*61046927SAndroid Build Coastguard Worker    virtual ir_visitor_status visit(ir_variable *var)
694*61046927SAndroid Build Coastguard Worker    {
695*61046927SAndroid Build Coastguard Worker       const glsl_type *type_without_array;
696*61046927SAndroid Build Coastguard Worker       bool implicit_sized_array = var->data.implicit_sized_array;
697*61046927SAndroid Build Coastguard Worker       fixup_type(&var->type, var->data.max_array_access,
698*61046927SAndroid Build Coastguard Worker                  var->data.from_ssbo_unsized_array,
699*61046927SAndroid Build Coastguard Worker                  &implicit_sized_array);
700*61046927SAndroid Build Coastguard Worker       var->data.implicit_sized_array = implicit_sized_array;
701*61046927SAndroid Build Coastguard Worker       type_without_array = glsl_without_array(var->type);
702*61046927SAndroid Build Coastguard Worker       if (glsl_type_is_interface(var->type)) {
703*61046927SAndroid Build Coastguard Worker          if (interface_contains_unsized_arrays(var->type)) {
704*61046927SAndroid Build Coastguard Worker             const glsl_type *new_type =
705*61046927SAndroid Build Coastguard Worker                resize_interface_members(var->type,
706*61046927SAndroid Build Coastguard Worker                                         var->get_max_ifc_array_access(),
707*61046927SAndroid Build Coastguard Worker                                         var->is_in_shader_storage_block());
708*61046927SAndroid Build Coastguard Worker             var->type = new_type;
709*61046927SAndroid Build Coastguard Worker             var->change_interface_type(new_type);
710*61046927SAndroid Build Coastguard Worker          }
711*61046927SAndroid Build Coastguard Worker       } else if (glsl_type_is_interface(type_without_array)) {
712*61046927SAndroid Build Coastguard Worker          if (interface_contains_unsized_arrays(type_without_array)) {
713*61046927SAndroid Build Coastguard Worker             const glsl_type *new_type =
714*61046927SAndroid Build Coastguard Worker                resize_interface_members(type_without_array,
715*61046927SAndroid Build Coastguard Worker                                         var->get_max_ifc_array_access(),
716*61046927SAndroid Build Coastguard Worker                                         var->is_in_shader_storage_block());
717*61046927SAndroid Build Coastguard Worker             var->change_interface_type(new_type);
718*61046927SAndroid Build Coastguard Worker             var->type = update_interface_members_array(var->type, new_type);
719*61046927SAndroid Build Coastguard Worker          }
720*61046927SAndroid Build Coastguard Worker       } else if (const glsl_type *ifc_type = var->get_interface_type()) {
721*61046927SAndroid Build Coastguard Worker          /* Store a pointer to the variable in the unnamed_interfaces
722*61046927SAndroid Build Coastguard Worker           * hashtable.
723*61046927SAndroid Build Coastguard Worker           */
724*61046927SAndroid Build Coastguard Worker          hash_entry *entry =
725*61046927SAndroid Build Coastguard Worker                _mesa_hash_table_search(this->unnamed_interfaces,
726*61046927SAndroid Build Coastguard Worker                                        ifc_type);
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker          ir_variable **interface_vars = entry ? (ir_variable **) entry->data : NULL;
729*61046927SAndroid Build Coastguard Worker 
730*61046927SAndroid Build Coastguard Worker          if (interface_vars == NULL) {
731*61046927SAndroid Build Coastguard Worker             interface_vars = rzalloc_array(mem_ctx, ir_variable *,
732*61046927SAndroid Build Coastguard Worker                                            ifc_type->length);
733*61046927SAndroid Build Coastguard Worker             _mesa_hash_table_insert(this->unnamed_interfaces, ifc_type,
734*61046927SAndroid Build Coastguard Worker                                     interface_vars);
735*61046927SAndroid Build Coastguard Worker          }
736*61046927SAndroid Build Coastguard Worker          unsigned index = glsl_get_field_index(ifc_type, var->name);
737*61046927SAndroid Build Coastguard Worker          assert(index < ifc_type->length);
738*61046927SAndroid Build Coastguard Worker          assert(interface_vars[index] == NULL);
739*61046927SAndroid Build Coastguard Worker          interface_vars[index] = var;
740*61046927SAndroid Build Coastguard Worker       }
741*61046927SAndroid Build Coastguard Worker       return visit_continue;
742*61046927SAndroid Build Coastguard Worker    }
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    /**
745*61046927SAndroid Build Coastguard Worker     * For each unnamed interface block that was discovered while running the
746*61046927SAndroid Build Coastguard Worker     * visitor, adjust the interface type to reflect the newly assigned array
747*61046927SAndroid Build Coastguard Worker     * sizes, and fix up the ir_variable nodes to point to the new interface
748*61046927SAndroid Build Coastguard Worker     * type.
749*61046927SAndroid Build Coastguard Worker     */
fixup_unnamed_interface_types()750*61046927SAndroid Build Coastguard Worker    void fixup_unnamed_interface_types()
751*61046927SAndroid Build Coastguard Worker    {
752*61046927SAndroid Build Coastguard Worker       hash_table_call_foreach(this->unnamed_interfaces,
753*61046927SAndroid Build Coastguard Worker                               fixup_unnamed_interface_type, NULL);
754*61046927SAndroid Build Coastguard Worker    }
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker private:
757*61046927SAndroid Build Coastguard Worker    /**
758*61046927SAndroid Build Coastguard Worker     * If the type pointed to by \c type represents an unsized array, replace
759*61046927SAndroid Build Coastguard Worker     * it with a sized array whose size is determined by max_array_access.
760*61046927SAndroid Build Coastguard Worker     */
fixup_type(const glsl_type ** type,unsigned max_array_access,bool from_ssbo_unsized_array,bool * implicit_sized)761*61046927SAndroid Build Coastguard Worker    static void fixup_type(const glsl_type **type, unsigned max_array_access,
762*61046927SAndroid Build Coastguard Worker                           bool from_ssbo_unsized_array, bool *implicit_sized)
763*61046927SAndroid Build Coastguard Worker    {
764*61046927SAndroid Build Coastguard Worker       if (!from_ssbo_unsized_array && glsl_type_is_unsized_array(*type)) {
765*61046927SAndroid Build Coastguard Worker          *type = glsl_array_type((*type)->fields.array,
766*61046927SAndroid Build Coastguard Worker                                  max_array_access + 1, 0);
767*61046927SAndroid Build Coastguard Worker          *implicit_sized = true;
768*61046927SAndroid Build Coastguard Worker          assert(*type != NULL);
769*61046927SAndroid Build Coastguard Worker       }
770*61046927SAndroid Build Coastguard Worker    }
771*61046927SAndroid Build Coastguard Worker 
772*61046927SAndroid Build Coastguard Worker    static const glsl_type *
update_interface_members_array(const glsl_type * type,const glsl_type * new_interface_type)773*61046927SAndroid Build Coastguard Worker    update_interface_members_array(const glsl_type *type,
774*61046927SAndroid Build Coastguard Worker                                   const glsl_type *new_interface_type)
775*61046927SAndroid Build Coastguard Worker    {
776*61046927SAndroid Build Coastguard Worker       const glsl_type *element_type = type->fields.array;
777*61046927SAndroid Build Coastguard Worker       if (glsl_type_is_array(element_type)) {
778*61046927SAndroid Build Coastguard Worker          const glsl_type *new_array_type =
779*61046927SAndroid Build Coastguard Worker             update_interface_members_array(element_type, new_interface_type);
780*61046927SAndroid Build Coastguard Worker          return glsl_array_type(new_array_type, type->length, 0);
781*61046927SAndroid Build Coastguard Worker       } else {
782*61046927SAndroid Build Coastguard Worker          return glsl_array_type(new_interface_type, type->length, 0);
783*61046927SAndroid Build Coastguard Worker       }
784*61046927SAndroid Build Coastguard Worker    }
785*61046927SAndroid Build Coastguard Worker 
786*61046927SAndroid Build Coastguard Worker    /**
787*61046927SAndroid Build Coastguard Worker     * Determine whether the given interface type contains unsized arrays (if
788*61046927SAndroid Build Coastguard Worker     * it doesn't, array_sizing_visitor doesn't need to process it).
789*61046927SAndroid Build Coastguard Worker     */
interface_contains_unsized_arrays(const glsl_type * type)790*61046927SAndroid Build Coastguard Worker    static bool interface_contains_unsized_arrays(const glsl_type *type)
791*61046927SAndroid Build Coastguard Worker    {
792*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < type->length; i++) {
793*61046927SAndroid Build Coastguard Worker          const glsl_type *elem_type = type->fields.structure[i].type;
794*61046927SAndroid Build Coastguard Worker          if (glsl_type_is_unsized_array(elem_type))
795*61046927SAndroid Build Coastguard Worker             return true;
796*61046927SAndroid Build Coastguard Worker       }
797*61046927SAndroid Build Coastguard Worker       return false;
798*61046927SAndroid Build Coastguard Worker    }
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker    /**
801*61046927SAndroid Build Coastguard Worker     * Create a new interface type based on the given type, with unsized arrays
802*61046927SAndroid Build Coastguard Worker     * replaced by sized arrays whose size is determined by
803*61046927SAndroid Build Coastguard Worker     * max_ifc_array_access.
804*61046927SAndroid Build Coastguard Worker     */
805*61046927SAndroid Build Coastguard Worker    static const glsl_type *
resize_interface_members(const glsl_type * type,const int * max_ifc_array_access,bool is_ssbo)806*61046927SAndroid Build Coastguard Worker    resize_interface_members(const glsl_type *type,
807*61046927SAndroid Build Coastguard Worker                             const int *max_ifc_array_access,
808*61046927SAndroid Build Coastguard Worker                             bool is_ssbo)
809*61046927SAndroid Build Coastguard Worker    {
810*61046927SAndroid Build Coastguard Worker       unsigned num_fields = type->length;
811*61046927SAndroid Build Coastguard Worker       glsl_struct_field *fields = new glsl_struct_field[num_fields];
812*61046927SAndroid Build Coastguard Worker       memcpy(fields, type->fields.structure,
813*61046927SAndroid Build Coastguard Worker              num_fields * sizeof(*fields));
814*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_fields; i++) {
815*61046927SAndroid Build Coastguard Worker          bool implicit_sized_array = fields[i].implicit_sized_array;
816*61046927SAndroid Build Coastguard Worker          /* If SSBO last member is unsized array, we don't replace it by a sized
817*61046927SAndroid Build Coastguard Worker           * array.
818*61046927SAndroid Build Coastguard Worker           */
819*61046927SAndroid Build Coastguard Worker          if (is_ssbo && i == (num_fields - 1))
820*61046927SAndroid Build Coastguard Worker             fixup_type(&fields[i].type, max_ifc_array_access[i],
821*61046927SAndroid Build Coastguard Worker                        true, &implicit_sized_array);
822*61046927SAndroid Build Coastguard Worker          else
823*61046927SAndroid Build Coastguard Worker             fixup_type(&fields[i].type, max_ifc_array_access[i],
824*61046927SAndroid Build Coastguard Worker                        false, &implicit_sized_array);
825*61046927SAndroid Build Coastguard Worker          fields[i].implicit_sized_array = implicit_sized_array;
826*61046927SAndroid Build Coastguard Worker       }
827*61046927SAndroid Build Coastguard Worker       glsl_interface_packing packing =
828*61046927SAndroid Build Coastguard Worker          (glsl_interface_packing) type->interface_packing;
829*61046927SAndroid Build Coastguard Worker       bool row_major = (bool) type->interface_row_major;
830*61046927SAndroid Build Coastguard Worker       const glsl_type *new_ifc_type =
831*61046927SAndroid Build Coastguard Worker          glsl_interface_type(fields, num_fields,
832*61046927SAndroid Build Coastguard Worker                              packing, row_major, glsl_get_type_name(type));
833*61046927SAndroid Build Coastguard Worker       delete [] fields;
834*61046927SAndroid Build Coastguard Worker       return new_ifc_type;
835*61046927SAndroid Build Coastguard Worker    }
836*61046927SAndroid Build Coastguard Worker 
fixup_unnamed_interface_type(const void * key,void * data,void *)837*61046927SAndroid Build Coastguard Worker    static void fixup_unnamed_interface_type(const void *key, void *data,
838*61046927SAndroid Build Coastguard Worker                                             void *)
839*61046927SAndroid Build Coastguard Worker    {
840*61046927SAndroid Build Coastguard Worker       const glsl_type *ifc_type = (const glsl_type *) key;
841*61046927SAndroid Build Coastguard Worker       ir_variable **interface_vars = (ir_variable **) data;
842*61046927SAndroid Build Coastguard Worker       unsigned num_fields = ifc_type->length;
843*61046927SAndroid Build Coastguard Worker       glsl_struct_field *fields = new glsl_struct_field[num_fields];
844*61046927SAndroid Build Coastguard Worker       memcpy(fields, ifc_type->fields.structure,
845*61046927SAndroid Build Coastguard Worker              num_fields * sizeof(*fields));
846*61046927SAndroid Build Coastguard Worker       bool interface_type_changed = false;
847*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_fields; i++) {
848*61046927SAndroid Build Coastguard Worker          if (interface_vars[i] != NULL &&
849*61046927SAndroid Build Coastguard Worker              fields[i].type != interface_vars[i]->type) {
850*61046927SAndroid Build Coastguard Worker             fields[i].type = interface_vars[i]->type;
851*61046927SAndroid Build Coastguard Worker             interface_type_changed = true;
852*61046927SAndroid Build Coastguard Worker          }
853*61046927SAndroid Build Coastguard Worker       }
854*61046927SAndroid Build Coastguard Worker       if (!interface_type_changed) {
855*61046927SAndroid Build Coastguard Worker          delete [] fields;
856*61046927SAndroid Build Coastguard Worker          return;
857*61046927SAndroid Build Coastguard Worker       }
858*61046927SAndroid Build Coastguard Worker       glsl_interface_packing packing =
859*61046927SAndroid Build Coastguard Worker          (glsl_interface_packing) ifc_type->interface_packing;
860*61046927SAndroid Build Coastguard Worker       bool row_major = (bool) ifc_type->interface_row_major;
861*61046927SAndroid Build Coastguard Worker       const glsl_type *new_ifc_type =
862*61046927SAndroid Build Coastguard Worker          glsl_interface_type(fields, num_fields, packing,
863*61046927SAndroid Build Coastguard Worker                              row_major, glsl_get_type_name(ifc_type));
864*61046927SAndroid Build Coastguard Worker       delete [] fields;
865*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_fields; i++) {
866*61046927SAndroid Build Coastguard Worker          if (interface_vars[i] != NULL)
867*61046927SAndroid Build Coastguard Worker             interface_vars[i]->change_interface_type(new_ifc_type);
868*61046927SAndroid Build Coastguard Worker       }
869*61046927SAndroid Build Coastguard Worker    }
870*61046927SAndroid Build Coastguard Worker 
871*61046927SAndroid Build Coastguard Worker    /**
872*61046927SAndroid Build Coastguard Worker     * Memory context used to allocate the data in \c unnamed_interfaces.
873*61046927SAndroid Build Coastguard Worker     */
874*61046927SAndroid Build Coastguard Worker    void *mem_ctx;
875*61046927SAndroid Build Coastguard Worker 
876*61046927SAndroid Build Coastguard Worker    /**
877*61046927SAndroid Build Coastguard Worker     * Hash table from const glsl_type * to an array of ir_variable *'s
878*61046927SAndroid Build Coastguard Worker     * pointing to the ir_variables constituting each unnamed interface block.
879*61046927SAndroid Build Coastguard Worker     */
880*61046927SAndroid Build Coastguard Worker    hash_table *unnamed_interfaces;
881*61046927SAndroid Build Coastguard Worker };
882*61046927SAndroid Build Coastguard Worker 
883*61046927SAndroid Build Coastguard Worker static bool
validate_xfb_buffer_stride(const struct gl_constants * consts,unsigned idx,struct gl_shader_program * prog)884*61046927SAndroid Build Coastguard Worker validate_xfb_buffer_stride(const struct gl_constants *consts, unsigned idx,
885*61046927SAndroid Build Coastguard Worker                            struct gl_shader_program *prog)
886*61046927SAndroid Build Coastguard Worker {
887*61046927SAndroid Build Coastguard Worker    /* We will validate doubles at a later stage */
888*61046927SAndroid Build Coastguard Worker    if (prog->TransformFeedback.BufferStride[idx] % 4) {
889*61046927SAndroid Build Coastguard Worker       linker_error(prog, "invalid qualifier xfb_stride=%d must be a "
890*61046927SAndroid Build Coastguard Worker                    "multiple of 4 or if its applied to a type that is "
891*61046927SAndroid Build Coastguard Worker                    "or contains a double a multiple of 8.",
892*61046927SAndroid Build Coastguard Worker                    prog->TransformFeedback.BufferStride[idx]);
893*61046927SAndroid Build Coastguard Worker       return false;
894*61046927SAndroid Build Coastguard Worker    }
895*61046927SAndroid Build Coastguard Worker 
896*61046927SAndroid Build Coastguard Worker    if (prog->TransformFeedback.BufferStride[idx] / 4 >
897*61046927SAndroid Build Coastguard Worker        consts->MaxTransformFeedbackInterleavedComponents) {
898*61046927SAndroid Build Coastguard Worker       linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
899*61046927SAndroid Build Coastguard Worker                    "limit has been exceeded.");
900*61046927SAndroid Build Coastguard Worker       return false;
901*61046927SAndroid Build Coastguard Worker    }
902*61046927SAndroid Build Coastguard Worker 
903*61046927SAndroid Build Coastguard Worker    return true;
904*61046927SAndroid Build Coastguard Worker }
905*61046927SAndroid Build Coastguard Worker 
906*61046927SAndroid Build Coastguard Worker /**
907*61046927SAndroid Build Coastguard Worker  * Check for conflicting xfb_stride default qualifiers and store buffer stride
908*61046927SAndroid Build Coastguard Worker  * for later use.
909*61046927SAndroid Build Coastguard Worker  */
910*61046927SAndroid Build Coastguard Worker static void
link_xfb_stride_layout_qualifiers(const struct gl_constants * consts,struct gl_shader_program * prog,struct gl_shader ** shader_list,unsigned num_shaders)911*61046927SAndroid Build Coastguard Worker link_xfb_stride_layout_qualifiers(const struct gl_constants *consts,
912*61046927SAndroid Build Coastguard Worker                                   struct gl_shader_program *prog,
913*61046927SAndroid Build Coastguard Worker                                   struct gl_shader **shader_list,
914*61046927SAndroid Build Coastguard Worker                                   unsigned num_shaders)
915*61046927SAndroid Build Coastguard Worker {
916*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
917*61046927SAndroid Build Coastguard Worker       prog->TransformFeedback.BufferStride[i] = 0;
918*61046927SAndroid Build Coastguard Worker    }
919*61046927SAndroid Build Coastguard Worker 
920*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
921*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker       for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
924*61046927SAndroid Build Coastguard Worker          if (shader->TransformFeedbackBufferStride[j]) {
925*61046927SAndroid Build Coastguard Worker             if (prog->TransformFeedback.BufferStride[j] == 0) {
926*61046927SAndroid Build Coastguard Worker                prog->TransformFeedback.BufferStride[j] =
927*61046927SAndroid Build Coastguard Worker                   shader->TransformFeedbackBufferStride[j];
928*61046927SAndroid Build Coastguard Worker                if (!validate_xfb_buffer_stride(consts, j, prog))
929*61046927SAndroid Build Coastguard Worker                   return;
930*61046927SAndroid Build Coastguard Worker             } else if (prog->TransformFeedback.BufferStride[j] !=
931*61046927SAndroid Build Coastguard Worker                        shader->TransformFeedbackBufferStride[j]){
932*61046927SAndroid Build Coastguard Worker                linker_error(prog,
933*61046927SAndroid Build Coastguard Worker                             "intrastage shaders defined with conflicting "
934*61046927SAndroid Build Coastguard Worker                             "xfb_stride for buffer %d (%d and %d)\n", j,
935*61046927SAndroid Build Coastguard Worker                             prog->TransformFeedback.BufferStride[j],
936*61046927SAndroid Build Coastguard Worker                             shader->TransformFeedbackBufferStride[j]);
937*61046927SAndroid Build Coastguard Worker                return;
938*61046927SAndroid Build Coastguard Worker             }
939*61046927SAndroid Build Coastguard Worker          }
940*61046927SAndroid Build Coastguard Worker       }
941*61046927SAndroid Build Coastguard Worker    }
942*61046927SAndroid Build Coastguard Worker }
943*61046927SAndroid Build Coastguard Worker 
944*61046927SAndroid Build Coastguard Worker /**
945*61046927SAndroid Build Coastguard Worker  * Check for conflicting bindless/bound sampler/image layout qualifiers at
946*61046927SAndroid Build Coastguard Worker  * global scope.
947*61046927SAndroid Build Coastguard Worker  */
948*61046927SAndroid Build Coastguard Worker static void
link_bindless_layout_qualifiers(struct gl_shader_program * prog,struct gl_shader ** shader_list,unsigned num_shaders)949*61046927SAndroid Build Coastguard Worker link_bindless_layout_qualifiers(struct gl_shader_program *prog,
950*61046927SAndroid Build Coastguard Worker                                 struct gl_shader **shader_list,
951*61046927SAndroid Build Coastguard Worker                                 unsigned num_shaders)
952*61046927SAndroid Build Coastguard Worker {
953*61046927SAndroid Build Coastguard Worker    bool bindless_sampler, bindless_image;
954*61046927SAndroid Build Coastguard Worker    bool bound_sampler, bound_image;
955*61046927SAndroid Build Coastguard Worker 
956*61046927SAndroid Build Coastguard Worker    bindless_sampler = bindless_image = false;
957*61046927SAndroid Build Coastguard Worker    bound_sampler = bound_image = false;
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
960*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker       if (shader->bindless_sampler)
963*61046927SAndroid Build Coastguard Worker          bindless_sampler = true;
964*61046927SAndroid Build Coastguard Worker       if (shader->bindless_image)
965*61046927SAndroid Build Coastguard Worker          bindless_image = true;
966*61046927SAndroid Build Coastguard Worker       if (shader->bound_sampler)
967*61046927SAndroid Build Coastguard Worker          bound_sampler = true;
968*61046927SAndroid Build Coastguard Worker       if (shader->bound_image)
969*61046927SAndroid Build Coastguard Worker          bound_image = true;
970*61046927SAndroid Build Coastguard Worker 
971*61046927SAndroid Build Coastguard Worker       if ((bindless_sampler && bound_sampler) ||
972*61046927SAndroid Build Coastguard Worker           (bindless_image && bound_image)) {
973*61046927SAndroid Build Coastguard Worker          /* From section 4.4.6 of the ARB_bindless_texture spec:
974*61046927SAndroid Build Coastguard Worker           *
975*61046927SAndroid Build Coastguard Worker           *     "If both bindless_sampler and bound_sampler, or bindless_image
976*61046927SAndroid Build Coastguard Worker           *      and bound_image, are declared at global scope in any
977*61046927SAndroid Build Coastguard Worker           *      compilation unit, a link- time error will be generated."
978*61046927SAndroid Build Coastguard Worker           */
979*61046927SAndroid Build Coastguard Worker          linker_error(prog, "both bindless_sampler and bound_sampler, or "
980*61046927SAndroid Build Coastguard Worker                       "bindless_image and bound_image, can't be declared at "
981*61046927SAndroid Build Coastguard Worker                       "global scope");
982*61046927SAndroid Build Coastguard Worker       }
983*61046927SAndroid Build Coastguard Worker    }
984*61046927SAndroid Build Coastguard Worker }
985*61046927SAndroid Build Coastguard Worker 
986*61046927SAndroid Build Coastguard Worker /**
987*61046927SAndroid Build Coastguard Worker  * Check for conflicting viewport_relative settings across shaders, and sets
988*61046927SAndroid Build Coastguard Worker  * the value for the linked shader.
989*61046927SAndroid Build Coastguard Worker  */
990*61046927SAndroid Build Coastguard Worker static void
link_layer_viewport_relative_qualifier(struct gl_shader_program * prog,struct gl_program * gl_prog,struct gl_shader ** shader_list,unsigned num_shaders)991*61046927SAndroid Build Coastguard Worker link_layer_viewport_relative_qualifier(struct gl_shader_program *prog,
992*61046927SAndroid Build Coastguard Worker                                        struct gl_program *gl_prog,
993*61046927SAndroid Build Coastguard Worker                                        struct gl_shader **shader_list,
994*61046927SAndroid Build Coastguard Worker                                        unsigned num_shaders)
995*61046927SAndroid Build Coastguard Worker {
996*61046927SAndroid Build Coastguard Worker    unsigned i;
997*61046927SAndroid Build Coastguard Worker 
998*61046927SAndroid Build Coastguard Worker    /* Find first shader with explicit layer declaration */
999*61046927SAndroid Build Coastguard Worker    for (i = 0; i < num_shaders; i++) {
1000*61046927SAndroid Build Coastguard Worker       if (shader_list[i]->redeclares_gl_layer) {
1001*61046927SAndroid Build Coastguard Worker          gl_prog->info.layer_viewport_relative =
1002*61046927SAndroid Build Coastguard Worker             shader_list[i]->layer_viewport_relative;
1003*61046927SAndroid Build Coastguard Worker          break;
1004*61046927SAndroid Build Coastguard Worker       }
1005*61046927SAndroid Build Coastguard Worker    }
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker    /* Now make sure that each subsequent shader's explicit layer declaration
1008*61046927SAndroid Build Coastguard Worker     * matches the first one's.
1009*61046927SAndroid Build Coastguard Worker     */
1010*61046927SAndroid Build Coastguard Worker    for (; i < num_shaders; i++) {
1011*61046927SAndroid Build Coastguard Worker       if (shader_list[i]->redeclares_gl_layer &&
1012*61046927SAndroid Build Coastguard Worker           shader_list[i]->layer_viewport_relative !=
1013*61046927SAndroid Build Coastguard Worker           gl_prog->info.layer_viewport_relative) {
1014*61046927SAndroid Build Coastguard Worker          linker_error(prog, "all gl_Layer redeclarations must have identical "
1015*61046927SAndroid Build Coastguard Worker                       "viewport_relative settings");
1016*61046927SAndroid Build Coastguard Worker       }
1017*61046927SAndroid Build Coastguard Worker    }
1018*61046927SAndroid Build Coastguard Worker }
1019*61046927SAndroid Build Coastguard Worker 
1020*61046927SAndroid Build Coastguard Worker /**
1021*61046927SAndroid Build Coastguard Worker  * Performs the cross-validation of tessellation control shader vertices and
1022*61046927SAndroid Build Coastguard Worker  * layout qualifiers for the attached tessellation control shaders,
1023*61046927SAndroid Build Coastguard Worker  * and propagates them to the linked TCS and linked shader program.
1024*61046927SAndroid Build Coastguard Worker  */
1025*61046927SAndroid Build Coastguard Worker static void
link_tcs_out_layout_qualifiers(struct gl_shader_program * prog,struct gl_program * gl_prog,struct gl_shader ** shader_list,unsigned num_shaders)1026*61046927SAndroid Build Coastguard Worker link_tcs_out_layout_qualifiers(struct gl_shader_program *prog,
1027*61046927SAndroid Build Coastguard Worker                                struct gl_program *gl_prog,
1028*61046927SAndroid Build Coastguard Worker                                struct gl_shader **shader_list,
1029*61046927SAndroid Build Coastguard Worker                                unsigned num_shaders)
1030*61046927SAndroid Build Coastguard Worker {
1031*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.stage != MESA_SHADER_TESS_CTRL)
1032*61046927SAndroid Build Coastguard Worker       return;
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker    gl_prog->info.tess.tcs_vertices_out = 0;
1035*61046927SAndroid Build Coastguard Worker 
1036*61046927SAndroid Build Coastguard Worker    /* From the GLSL 4.0 spec (chapter 4.3.8.2):
1037*61046927SAndroid Build Coastguard Worker     *
1038*61046927SAndroid Build Coastguard Worker     *     "All tessellation control shader layout declarations in a program
1039*61046927SAndroid Build Coastguard Worker     *      must specify the same output patch vertex count.  There must be at
1040*61046927SAndroid Build Coastguard Worker     *      least one layout qualifier specifying an output patch vertex count
1041*61046927SAndroid Build Coastguard Worker     *      in any program containing tessellation control shaders; however,
1042*61046927SAndroid Build Coastguard Worker     *      such a declaration is not required in all tessellation control
1043*61046927SAndroid Build Coastguard Worker     *      shaders."
1044*61046927SAndroid Build Coastguard Worker     */
1045*61046927SAndroid Build Coastguard Worker 
1046*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1047*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
1048*61046927SAndroid Build Coastguard Worker 
1049*61046927SAndroid Build Coastguard Worker       if (shader->info.TessCtrl.VerticesOut != 0) {
1050*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.tess.tcs_vertices_out != 0 &&
1051*61046927SAndroid Build Coastguard Worker              gl_prog->info.tess.tcs_vertices_out !=
1052*61046927SAndroid Build Coastguard Worker              (unsigned) shader->info.TessCtrl.VerticesOut) {
1053*61046927SAndroid Build Coastguard Worker             linker_error(prog, "tessellation control shader defined with "
1054*61046927SAndroid Build Coastguard Worker                          "conflicting output vertex count (%d and %d)\n",
1055*61046927SAndroid Build Coastguard Worker                          gl_prog->info.tess.tcs_vertices_out,
1056*61046927SAndroid Build Coastguard Worker                          shader->info.TessCtrl.VerticesOut);
1057*61046927SAndroid Build Coastguard Worker             return;
1058*61046927SAndroid Build Coastguard Worker          }
1059*61046927SAndroid Build Coastguard Worker          gl_prog->info.tess.tcs_vertices_out =
1060*61046927SAndroid Build Coastguard Worker             shader->info.TessCtrl.VerticesOut;
1061*61046927SAndroid Build Coastguard Worker       }
1062*61046927SAndroid Build Coastguard Worker    }
1063*61046927SAndroid Build Coastguard Worker 
1064*61046927SAndroid Build Coastguard Worker    /* Just do the intrastage -> interstage propagation right now,
1065*61046927SAndroid Build Coastguard Worker     * since we already know we're in the right type of shader program
1066*61046927SAndroid Build Coastguard Worker     * for doing it.
1067*61046927SAndroid Build Coastguard Worker     */
1068*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.tess.tcs_vertices_out == 0) {
1069*61046927SAndroid Build Coastguard Worker       linker_error(prog, "tessellation control shader didn't declare "
1070*61046927SAndroid Build Coastguard Worker                    "vertices out layout qualifier\n");
1071*61046927SAndroid Build Coastguard Worker       return;
1072*61046927SAndroid Build Coastguard Worker    }
1073*61046927SAndroid Build Coastguard Worker }
1074*61046927SAndroid Build Coastguard Worker 
1075*61046927SAndroid Build Coastguard Worker 
1076*61046927SAndroid Build Coastguard Worker /**
1077*61046927SAndroid Build Coastguard Worker  * Performs the cross-validation of tessellation evaluation shader
1078*61046927SAndroid Build Coastguard Worker  * primitive type, vertex spacing, ordering and point_mode layout qualifiers
1079*61046927SAndroid Build Coastguard Worker  * for the attached tessellation evaluation shaders, and propagates them
1080*61046927SAndroid Build Coastguard Worker  * to the linked TES and linked shader program.
1081*61046927SAndroid Build Coastguard Worker  */
1082*61046927SAndroid Build Coastguard Worker static void
link_tes_in_layout_qualifiers(struct gl_shader_program * prog,struct gl_program * gl_prog,struct gl_shader ** shader_list,unsigned num_shaders)1083*61046927SAndroid Build Coastguard Worker link_tes_in_layout_qualifiers(struct gl_shader_program *prog,
1084*61046927SAndroid Build Coastguard Worker                               struct gl_program *gl_prog,
1085*61046927SAndroid Build Coastguard Worker                               struct gl_shader **shader_list,
1086*61046927SAndroid Build Coastguard Worker                               unsigned num_shaders)
1087*61046927SAndroid Build Coastguard Worker {
1088*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.stage != MESA_SHADER_TESS_EVAL)
1089*61046927SAndroid Build Coastguard Worker       return;
1090*61046927SAndroid Build Coastguard Worker 
1091*61046927SAndroid Build Coastguard Worker    int point_mode = -1;
1092*61046927SAndroid Build Coastguard Worker    unsigned vertex_order = 0;
1093*61046927SAndroid Build Coastguard Worker 
1094*61046927SAndroid Build Coastguard Worker    gl_prog->info.tess._primitive_mode = TESS_PRIMITIVE_UNSPECIFIED;
1095*61046927SAndroid Build Coastguard Worker    gl_prog->info.tess.spacing = TESS_SPACING_UNSPECIFIED;
1096*61046927SAndroid Build Coastguard Worker 
1097*61046927SAndroid Build Coastguard Worker    /* From the GLSL 4.0 spec (chapter 4.3.8.1):
1098*61046927SAndroid Build Coastguard Worker     *
1099*61046927SAndroid Build Coastguard Worker     *     "At least one tessellation evaluation shader (compilation unit) in
1100*61046927SAndroid Build Coastguard Worker     *      a program must declare a primitive mode in its input layout.
1101*61046927SAndroid Build Coastguard Worker     *      Declaration vertex spacing, ordering, and point mode identifiers is
1102*61046927SAndroid Build Coastguard Worker     *      optional.  It is not required that all tessellation evaluation
1103*61046927SAndroid Build Coastguard Worker     *      shaders in a program declare a primitive mode.  If spacing or
1104*61046927SAndroid Build Coastguard Worker     *      vertex ordering declarations are omitted, the tessellation
1105*61046927SAndroid Build Coastguard Worker     *      primitive generator will use equal spacing or counter-clockwise
1106*61046927SAndroid Build Coastguard Worker     *      vertex ordering, respectively.  If a point mode declaration is
1107*61046927SAndroid Build Coastguard Worker     *      omitted, the tessellation primitive generator will produce lines or
1108*61046927SAndroid Build Coastguard Worker     *      triangles according to the primitive mode."
1109*61046927SAndroid Build Coastguard Worker     */
1110*61046927SAndroid Build Coastguard Worker 
1111*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1112*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
1113*61046927SAndroid Build Coastguard Worker 
1114*61046927SAndroid Build Coastguard Worker       if (shader->info.TessEval._PrimitiveMode != TESS_PRIMITIVE_UNSPECIFIED) {
1115*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.tess._primitive_mode != TESS_PRIMITIVE_UNSPECIFIED &&
1116*61046927SAndroid Build Coastguard Worker              gl_prog->info.tess._primitive_mode !=
1117*61046927SAndroid Build Coastguard Worker              shader->info.TessEval._PrimitiveMode) {
1118*61046927SAndroid Build Coastguard Worker             linker_error(prog, "tessellation evaluation shader defined with "
1119*61046927SAndroid Build Coastguard Worker                          "conflicting input primitive modes.\n");
1120*61046927SAndroid Build Coastguard Worker             return;
1121*61046927SAndroid Build Coastguard Worker          }
1122*61046927SAndroid Build Coastguard Worker          gl_prog->info.tess._primitive_mode =
1123*61046927SAndroid Build Coastguard Worker             shader->info.TessEval._PrimitiveMode;
1124*61046927SAndroid Build Coastguard Worker       }
1125*61046927SAndroid Build Coastguard Worker 
1126*61046927SAndroid Build Coastguard Worker       if (shader->info.TessEval.Spacing != 0) {
1127*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.tess.spacing != 0 && gl_prog->info.tess.spacing !=
1128*61046927SAndroid Build Coastguard Worker              shader->info.TessEval.Spacing) {
1129*61046927SAndroid Build Coastguard Worker             linker_error(prog, "tessellation evaluation shader defined with "
1130*61046927SAndroid Build Coastguard Worker                          "conflicting vertex spacing.\n");
1131*61046927SAndroid Build Coastguard Worker             return;
1132*61046927SAndroid Build Coastguard Worker          }
1133*61046927SAndroid Build Coastguard Worker          gl_prog->info.tess.spacing = shader->info.TessEval.Spacing;
1134*61046927SAndroid Build Coastguard Worker       }
1135*61046927SAndroid Build Coastguard Worker 
1136*61046927SAndroid Build Coastguard Worker       if (shader->info.TessEval.VertexOrder != 0) {
1137*61046927SAndroid Build Coastguard Worker          if (vertex_order != 0 &&
1138*61046927SAndroid Build Coastguard Worker              vertex_order != shader->info.TessEval.VertexOrder) {
1139*61046927SAndroid Build Coastguard Worker             linker_error(prog, "tessellation evaluation shader defined with "
1140*61046927SAndroid Build Coastguard Worker                          "conflicting ordering.\n");
1141*61046927SAndroid Build Coastguard Worker             return;
1142*61046927SAndroid Build Coastguard Worker          }
1143*61046927SAndroid Build Coastguard Worker          vertex_order = shader->info.TessEval.VertexOrder;
1144*61046927SAndroid Build Coastguard Worker       }
1145*61046927SAndroid Build Coastguard Worker 
1146*61046927SAndroid Build Coastguard Worker       if (shader->info.TessEval.PointMode != -1) {
1147*61046927SAndroid Build Coastguard Worker          if (point_mode != -1 &&
1148*61046927SAndroid Build Coastguard Worker              point_mode != shader->info.TessEval.PointMode) {
1149*61046927SAndroid Build Coastguard Worker             linker_error(prog, "tessellation evaluation shader defined with "
1150*61046927SAndroid Build Coastguard Worker                          "conflicting point modes.\n");
1151*61046927SAndroid Build Coastguard Worker             return;
1152*61046927SAndroid Build Coastguard Worker          }
1153*61046927SAndroid Build Coastguard Worker          point_mode = shader->info.TessEval.PointMode;
1154*61046927SAndroid Build Coastguard Worker       }
1155*61046927SAndroid Build Coastguard Worker 
1156*61046927SAndroid Build Coastguard Worker    }
1157*61046927SAndroid Build Coastguard Worker 
1158*61046927SAndroid Build Coastguard Worker    /* Just do the intrastage -> interstage propagation right now,
1159*61046927SAndroid Build Coastguard Worker     * since we already know we're in the right type of shader program
1160*61046927SAndroid Build Coastguard Worker     * for doing it.
1161*61046927SAndroid Build Coastguard Worker     */
1162*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.tess._primitive_mode == TESS_PRIMITIVE_UNSPECIFIED) {
1163*61046927SAndroid Build Coastguard Worker       linker_error(prog,
1164*61046927SAndroid Build Coastguard Worker                    "tessellation evaluation shader didn't declare input "
1165*61046927SAndroid Build Coastguard Worker                    "primitive modes.\n");
1166*61046927SAndroid Build Coastguard Worker       return;
1167*61046927SAndroid Build Coastguard Worker    }
1168*61046927SAndroid Build Coastguard Worker 
1169*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.tess.spacing == TESS_SPACING_UNSPECIFIED)
1170*61046927SAndroid Build Coastguard Worker       gl_prog->info.tess.spacing = TESS_SPACING_EQUAL;
1171*61046927SAndroid Build Coastguard Worker 
1172*61046927SAndroid Build Coastguard Worker    if (vertex_order == 0 || vertex_order == GL_CCW)
1173*61046927SAndroid Build Coastguard Worker       gl_prog->info.tess.ccw = true;
1174*61046927SAndroid Build Coastguard Worker    else
1175*61046927SAndroid Build Coastguard Worker       gl_prog->info.tess.ccw = false;
1176*61046927SAndroid Build Coastguard Worker 
1177*61046927SAndroid Build Coastguard Worker 
1178*61046927SAndroid Build Coastguard Worker    if (point_mode == -1 || point_mode == GL_FALSE)
1179*61046927SAndroid Build Coastguard Worker       gl_prog->info.tess.point_mode = false;
1180*61046927SAndroid Build Coastguard Worker    else
1181*61046927SAndroid Build Coastguard Worker       gl_prog->info.tess.point_mode = true;
1182*61046927SAndroid Build Coastguard Worker }
1183*61046927SAndroid Build Coastguard Worker 
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker /**
1186*61046927SAndroid Build Coastguard Worker  * Performs the cross-validation of layout qualifiers specified in
1187*61046927SAndroid Build Coastguard Worker  * redeclaration of gl_FragCoord for the attached fragment shaders,
1188*61046927SAndroid Build Coastguard Worker  * and propagates them to the linked FS and linked shader program.
1189*61046927SAndroid Build Coastguard Worker  */
1190*61046927SAndroid Build Coastguard Worker static void
link_fs_inout_layout_qualifiers(struct gl_shader_program * prog,struct gl_linked_shader * linked_shader,struct gl_shader ** shader_list,unsigned num_shaders,bool arb_fragment_coord_conventions_enable)1191*61046927SAndroid Build Coastguard Worker link_fs_inout_layout_qualifiers(struct gl_shader_program *prog,
1192*61046927SAndroid Build Coastguard Worker                                 struct gl_linked_shader *linked_shader,
1193*61046927SAndroid Build Coastguard Worker                                 struct gl_shader **shader_list,
1194*61046927SAndroid Build Coastguard Worker                                 unsigned num_shaders,
1195*61046927SAndroid Build Coastguard Worker                                 bool arb_fragment_coord_conventions_enable)
1196*61046927SAndroid Build Coastguard Worker {
1197*61046927SAndroid Build Coastguard Worker    bool redeclares_gl_fragcoord = false;
1198*61046927SAndroid Build Coastguard Worker    bool uses_gl_fragcoord = false;
1199*61046927SAndroid Build Coastguard Worker    bool origin_upper_left = false;
1200*61046927SAndroid Build Coastguard Worker    bool pixel_center_integer = false;
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker    if (linked_shader->Stage != MESA_SHADER_FRAGMENT ||
1203*61046927SAndroid Build Coastguard Worker        (prog->GLSL_Version < 150 && !arb_fragment_coord_conventions_enable))
1204*61046927SAndroid Build Coastguard Worker       return;
1205*61046927SAndroid Build Coastguard Worker 
1206*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1207*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
1208*61046927SAndroid Build Coastguard Worker       /* From the GLSL 1.50 spec, page 39:
1209*61046927SAndroid Build Coastguard Worker        *
1210*61046927SAndroid Build Coastguard Worker        *   "If gl_FragCoord is redeclared in any fragment shader in a program,
1211*61046927SAndroid Build Coastguard Worker        *    it must be redeclared in all the fragment shaders in that program
1212*61046927SAndroid Build Coastguard Worker        *    that have a static use gl_FragCoord."
1213*61046927SAndroid Build Coastguard Worker        */
1214*61046927SAndroid Build Coastguard Worker       if ((redeclares_gl_fragcoord && !shader->redeclares_gl_fragcoord &&
1215*61046927SAndroid Build Coastguard Worker            shader->uses_gl_fragcoord)
1216*61046927SAndroid Build Coastguard Worker           || (shader->redeclares_gl_fragcoord && !redeclares_gl_fragcoord &&
1217*61046927SAndroid Build Coastguard Worker               uses_gl_fragcoord)) {
1218*61046927SAndroid Build Coastguard Worker              linker_error(prog, "fragment shader defined with conflicting "
1219*61046927SAndroid Build Coastguard Worker                          "layout qualifiers for gl_FragCoord\n");
1220*61046927SAndroid Build Coastguard Worker       }
1221*61046927SAndroid Build Coastguard Worker 
1222*61046927SAndroid Build Coastguard Worker       /* From the GLSL 1.50 spec, page 39:
1223*61046927SAndroid Build Coastguard Worker        *
1224*61046927SAndroid Build Coastguard Worker        *   "All redeclarations of gl_FragCoord in all fragment shaders in a
1225*61046927SAndroid Build Coastguard Worker        *    single program must have the same set of qualifiers."
1226*61046927SAndroid Build Coastguard Worker        */
1227*61046927SAndroid Build Coastguard Worker       if (redeclares_gl_fragcoord && shader->redeclares_gl_fragcoord &&
1228*61046927SAndroid Build Coastguard Worker           (shader->origin_upper_left != origin_upper_left ||
1229*61046927SAndroid Build Coastguard Worker            shader->pixel_center_integer != pixel_center_integer)) {
1230*61046927SAndroid Build Coastguard Worker          linker_error(prog, "fragment shader defined with conflicting "
1231*61046927SAndroid Build Coastguard Worker                       "layout qualifiers for gl_FragCoord\n");
1232*61046927SAndroid Build Coastguard Worker       }
1233*61046927SAndroid Build Coastguard Worker 
1234*61046927SAndroid Build Coastguard Worker       /* Update the linked shader state.  Note that uses_gl_fragcoord should
1235*61046927SAndroid Build Coastguard Worker        * accumulate the results.  The other values should replace.  If there
1236*61046927SAndroid Build Coastguard Worker        * are multiple redeclarations, all the fields except uses_gl_fragcoord
1237*61046927SAndroid Build Coastguard Worker        * are already known to be the same.
1238*61046927SAndroid Build Coastguard Worker        */
1239*61046927SAndroid Build Coastguard Worker       if (shader->redeclares_gl_fragcoord || shader->uses_gl_fragcoord) {
1240*61046927SAndroid Build Coastguard Worker          redeclares_gl_fragcoord = shader->redeclares_gl_fragcoord;
1241*61046927SAndroid Build Coastguard Worker          uses_gl_fragcoord |= shader->uses_gl_fragcoord;
1242*61046927SAndroid Build Coastguard Worker          origin_upper_left = shader->origin_upper_left;
1243*61046927SAndroid Build Coastguard Worker          pixel_center_integer = shader->pixel_center_integer;
1244*61046927SAndroid Build Coastguard Worker       }
1245*61046927SAndroid Build Coastguard Worker 
1246*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.early_fragment_tests |=
1247*61046927SAndroid Build Coastguard Worker          shader->EarlyFragmentTests || shader->PostDepthCoverage;
1248*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.inner_coverage |= shader->InnerCoverage;
1249*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.post_depth_coverage |=
1250*61046927SAndroid Build Coastguard Worker          shader->PostDepthCoverage;
1251*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.pixel_interlock_ordered |=
1252*61046927SAndroid Build Coastguard Worker          shader->PixelInterlockOrdered;
1253*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.pixel_interlock_unordered |=
1254*61046927SAndroid Build Coastguard Worker          shader->PixelInterlockUnordered;
1255*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.sample_interlock_ordered |=
1256*61046927SAndroid Build Coastguard Worker          shader->SampleInterlockOrdered;
1257*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.sample_interlock_unordered |=
1258*61046927SAndroid Build Coastguard Worker          shader->SampleInterlockUnordered;
1259*61046927SAndroid Build Coastguard Worker       linked_shader->Program->info.fs.advanced_blend_modes |= shader->BlendSupport;
1260*61046927SAndroid Build Coastguard Worker    }
1261*61046927SAndroid Build Coastguard Worker 
1262*61046927SAndroid Build Coastguard Worker    linked_shader->Program->info.fs.pixel_center_integer = pixel_center_integer;
1263*61046927SAndroid Build Coastguard Worker    linked_shader->Program->info.fs.origin_upper_left = origin_upper_left;
1264*61046927SAndroid Build Coastguard Worker }
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker /**
1267*61046927SAndroid Build Coastguard Worker  * Performs the cross-validation of geometry shader max_vertices and
1268*61046927SAndroid Build Coastguard Worker  * primitive type layout qualifiers for the attached geometry shaders,
1269*61046927SAndroid Build Coastguard Worker  * and propagates them to the linked GS and linked shader program.
1270*61046927SAndroid Build Coastguard Worker  */
1271*61046927SAndroid Build Coastguard Worker static void
link_gs_inout_layout_qualifiers(struct gl_shader_program * prog,struct gl_program * gl_prog,struct gl_shader ** shader_list,unsigned num_shaders)1272*61046927SAndroid Build Coastguard Worker link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
1273*61046927SAndroid Build Coastguard Worker                                 struct gl_program *gl_prog,
1274*61046927SAndroid Build Coastguard Worker                                 struct gl_shader **shader_list,
1275*61046927SAndroid Build Coastguard Worker                                 unsigned num_shaders)
1276*61046927SAndroid Build Coastguard Worker {
1277*61046927SAndroid Build Coastguard Worker    /* No in/out qualifiers defined for anything but GLSL 1.50+
1278*61046927SAndroid Build Coastguard Worker     * geometry shaders so far.
1279*61046927SAndroid Build Coastguard Worker     */
1280*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.stage != MESA_SHADER_GEOMETRY || prog->GLSL_Version < 150)
1281*61046927SAndroid Build Coastguard Worker       return;
1282*61046927SAndroid Build Coastguard Worker 
1283*61046927SAndroid Build Coastguard Worker    int vertices_out = -1;
1284*61046927SAndroid Build Coastguard Worker 
1285*61046927SAndroid Build Coastguard Worker    gl_prog->info.gs.invocations = 0;
1286*61046927SAndroid Build Coastguard Worker    gl_prog->info.gs.input_primitive = MESA_PRIM_UNKNOWN;
1287*61046927SAndroid Build Coastguard Worker    gl_prog->info.gs.output_primitive = MESA_PRIM_UNKNOWN;
1288*61046927SAndroid Build Coastguard Worker 
1289*61046927SAndroid Build Coastguard Worker    /* From the GLSL 1.50 spec, page 46:
1290*61046927SAndroid Build Coastguard Worker     *
1291*61046927SAndroid Build Coastguard Worker     *     "All geometry shader output layout declarations in a program
1292*61046927SAndroid Build Coastguard Worker     *      must declare the same layout and same value for
1293*61046927SAndroid Build Coastguard Worker     *      max_vertices. There must be at least one geometry output
1294*61046927SAndroid Build Coastguard Worker     *      layout declaration somewhere in a program, but not all
1295*61046927SAndroid Build Coastguard Worker     *      geometry shaders (compilation units) are required to
1296*61046927SAndroid Build Coastguard Worker     *      declare it."
1297*61046927SAndroid Build Coastguard Worker     */
1298*61046927SAndroid Build Coastguard Worker 
1299*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1300*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[i];
1301*61046927SAndroid Build Coastguard Worker 
1302*61046927SAndroid Build Coastguard Worker       if (shader->info.Geom.InputType != MESA_PRIM_UNKNOWN) {
1303*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.gs.input_primitive != MESA_PRIM_UNKNOWN &&
1304*61046927SAndroid Build Coastguard Worker              gl_prog->info.gs.input_primitive !=
1305*61046927SAndroid Build Coastguard Worker              shader->info.Geom.InputType) {
1306*61046927SAndroid Build Coastguard Worker             linker_error(prog, "geometry shader defined with conflicting "
1307*61046927SAndroid Build Coastguard Worker                          "input types\n");
1308*61046927SAndroid Build Coastguard Worker             return;
1309*61046927SAndroid Build Coastguard Worker          }
1310*61046927SAndroid Build Coastguard Worker          gl_prog->info.gs.input_primitive = (enum mesa_prim)shader->info.Geom.InputType;
1311*61046927SAndroid Build Coastguard Worker       }
1312*61046927SAndroid Build Coastguard Worker 
1313*61046927SAndroid Build Coastguard Worker       if (shader->info.Geom.OutputType != MESA_PRIM_UNKNOWN) {
1314*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.gs.output_primitive != MESA_PRIM_UNKNOWN &&
1315*61046927SAndroid Build Coastguard Worker              gl_prog->info.gs.output_primitive !=
1316*61046927SAndroid Build Coastguard Worker              shader->info.Geom.OutputType) {
1317*61046927SAndroid Build Coastguard Worker             linker_error(prog, "geometry shader defined with conflicting "
1318*61046927SAndroid Build Coastguard Worker                          "output types\n");
1319*61046927SAndroid Build Coastguard Worker             return;
1320*61046927SAndroid Build Coastguard Worker          }
1321*61046927SAndroid Build Coastguard Worker          gl_prog->info.gs.output_primitive = (enum mesa_prim)shader->info.Geom.OutputType;
1322*61046927SAndroid Build Coastguard Worker       }
1323*61046927SAndroid Build Coastguard Worker 
1324*61046927SAndroid Build Coastguard Worker       if (shader->info.Geom.VerticesOut != -1) {
1325*61046927SAndroid Build Coastguard Worker          if (vertices_out != -1 &&
1326*61046927SAndroid Build Coastguard Worker              vertices_out != shader->info.Geom.VerticesOut) {
1327*61046927SAndroid Build Coastguard Worker             linker_error(prog, "geometry shader defined with conflicting "
1328*61046927SAndroid Build Coastguard Worker                          "output vertex count (%d and %d)\n",
1329*61046927SAndroid Build Coastguard Worker                          vertices_out, shader->info.Geom.VerticesOut);
1330*61046927SAndroid Build Coastguard Worker             return;
1331*61046927SAndroid Build Coastguard Worker          }
1332*61046927SAndroid Build Coastguard Worker          vertices_out = shader->info.Geom.VerticesOut;
1333*61046927SAndroid Build Coastguard Worker       }
1334*61046927SAndroid Build Coastguard Worker 
1335*61046927SAndroid Build Coastguard Worker       if (shader->info.Geom.Invocations != 0) {
1336*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.gs.invocations != 0 &&
1337*61046927SAndroid Build Coastguard Worker              gl_prog->info.gs.invocations !=
1338*61046927SAndroid Build Coastguard Worker              (unsigned) shader->info.Geom.Invocations) {
1339*61046927SAndroid Build Coastguard Worker             linker_error(prog, "geometry shader defined with conflicting "
1340*61046927SAndroid Build Coastguard Worker                          "invocation count (%d and %d)\n",
1341*61046927SAndroid Build Coastguard Worker                          gl_prog->info.gs.invocations,
1342*61046927SAndroid Build Coastguard Worker                          shader->info.Geom.Invocations);
1343*61046927SAndroid Build Coastguard Worker             return;
1344*61046927SAndroid Build Coastguard Worker          }
1345*61046927SAndroid Build Coastguard Worker          gl_prog->info.gs.invocations = shader->info.Geom.Invocations;
1346*61046927SAndroid Build Coastguard Worker       }
1347*61046927SAndroid Build Coastguard Worker    }
1348*61046927SAndroid Build Coastguard Worker 
1349*61046927SAndroid Build Coastguard Worker    /* Just do the intrastage -> interstage propagation right now,
1350*61046927SAndroid Build Coastguard Worker     * since we already know we're in the right type of shader program
1351*61046927SAndroid Build Coastguard Worker     * for doing it.
1352*61046927SAndroid Build Coastguard Worker     */
1353*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.gs.input_primitive == MESA_PRIM_UNKNOWN) {
1354*61046927SAndroid Build Coastguard Worker       linker_error(prog,
1355*61046927SAndroid Build Coastguard Worker                    "geometry shader didn't declare primitive input type\n");
1356*61046927SAndroid Build Coastguard Worker       return;
1357*61046927SAndroid Build Coastguard Worker    }
1358*61046927SAndroid Build Coastguard Worker 
1359*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.gs.output_primitive == MESA_PRIM_UNKNOWN) {
1360*61046927SAndroid Build Coastguard Worker       linker_error(prog,
1361*61046927SAndroid Build Coastguard Worker                    "geometry shader didn't declare primitive output type\n");
1362*61046927SAndroid Build Coastguard Worker       return;
1363*61046927SAndroid Build Coastguard Worker    }
1364*61046927SAndroid Build Coastguard Worker 
1365*61046927SAndroid Build Coastguard Worker    if (vertices_out == -1) {
1366*61046927SAndroid Build Coastguard Worker       linker_error(prog,
1367*61046927SAndroid Build Coastguard Worker                    "geometry shader didn't declare max_vertices\n");
1368*61046927SAndroid Build Coastguard Worker       return;
1369*61046927SAndroid Build Coastguard Worker    } else {
1370*61046927SAndroid Build Coastguard Worker       gl_prog->info.gs.vertices_out = vertices_out;
1371*61046927SAndroid Build Coastguard Worker    }
1372*61046927SAndroid Build Coastguard Worker 
1373*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.gs.invocations == 0)
1374*61046927SAndroid Build Coastguard Worker       gl_prog->info.gs.invocations = 1;
1375*61046927SAndroid Build Coastguard Worker }
1376*61046927SAndroid Build Coastguard Worker 
1377*61046927SAndroid Build Coastguard Worker 
1378*61046927SAndroid Build Coastguard Worker /**
1379*61046927SAndroid Build Coastguard Worker  * Perform cross-validation of compute shader local_size_{x,y,z} layout and
1380*61046927SAndroid Build Coastguard Worker  * derivative arrangement qualifiers for the attached compute shaders, and
1381*61046927SAndroid Build Coastguard Worker  * propagate them to the linked CS and linked shader program.
1382*61046927SAndroid Build Coastguard Worker  */
1383*61046927SAndroid Build Coastguard Worker static void
link_cs_input_layout_qualifiers(struct gl_shader_program * prog,struct gl_program * gl_prog,struct gl_shader ** shader_list,unsigned num_shaders)1384*61046927SAndroid Build Coastguard Worker link_cs_input_layout_qualifiers(struct gl_shader_program *prog,
1385*61046927SAndroid Build Coastguard Worker                                 struct gl_program *gl_prog,
1386*61046927SAndroid Build Coastguard Worker                                 struct gl_shader **shader_list,
1387*61046927SAndroid Build Coastguard Worker                                 unsigned num_shaders)
1388*61046927SAndroid Build Coastguard Worker {
1389*61046927SAndroid Build Coastguard Worker    /* This function is called for all shader stages, but it only has an effect
1390*61046927SAndroid Build Coastguard Worker     * for compute shaders.
1391*61046927SAndroid Build Coastguard Worker     */
1392*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.stage != MESA_SHADER_COMPUTE)
1393*61046927SAndroid Build Coastguard Worker       return;
1394*61046927SAndroid Build Coastguard Worker 
1395*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 3; i++)
1396*61046927SAndroid Build Coastguard Worker       gl_prog->info.workgroup_size[i] = 0;
1397*61046927SAndroid Build Coastguard Worker 
1398*61046927SAndroid Build Coastguard Worker    gl_prog->info.workgroup_size_variable = false;
1399*61046927SAndroid Build Coastguard Worker 
1400*61046927SAndroid Build Coastguard Worker    gl_prog->info.derivative_group = DERIVATIVE_GROUP_NONE;
1401*61046927SAndroid Build Coastguard Worker 
1402*61046927SAndroid Build Coastguard Worker    /* From the ARB_compute_shader spec, in the section describing local size
1403*61046927SAndroid Build Coastguard Worker     * declarations:
1404*61046927SAndroid Build Coastguard Worker     *
1405*61046927SAndroid Build Coastguard Worker     *     If multiple compute shaders attached to a single program object
1406*61046927SAndroid Build Coastguard Worker     *     declare local work-group size, the declarations must be identical;
1407*61046927SAndroid Build Coastguard Worker     *     otherwise a link-time error results. Furthermore, if a program
1408*61046927SAndroid Build Coastguard Worker     *     object contains any compute shaders, at least one must contain an
1409*61046927SAndroid Build Coastguard Worker     *     input layout qualifier specifying the local work sizes of the
1410*61046927SAndroid Build Coastguard Worker     *     program, or a link-time error will occur.
1411*61046927SAndroid Build Coastguard Worker     */
1412*61046927SAndroid Build Coastguard Worker    for (unsigned sh = 0; sh < num_shaders; sh++) {
1413*61046927SAndroid Build Coastguard Worker       struct gl_shader *shader = shader_list[sh];
1414*61046927SAndroid Build Coastguard Worker 
1415*61046927SAndroid Build Coastguard Worker       if (shader->info.Comp.LocalSize[0] != 0) {
1416*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.workgroup_size[0] != 0) {
1417*61046927SAndroid Build Coastguard Worker             for (int i = 0; i < 3; i++) {
1418*61046927SAndroid Build Coastguard Worker                if (gl_prog->info.workgroup_size[i] !=
1419*61046927SAndroid Build Coastguard Worker                    shader->info.Comp.LocalSize[i]) {
1420*61046927SAndroid Build Coastguard Worker                   linker_error(prog, "compute shader defined with conflicting "
1421*61046927SAndroid Build Coastguard Worker                                "local sizes\n");
1422*61046927SAndroid Build Coastguard Worker                   return;
1423*61046927SAndroid Build Coastguard Worker                }
1424*61046927SAndroid Build Coastguard Worker             }
1425*61046927SAndroid Build Coastguard Worker          }
1426*61046927SAndroid Build Coastguard Worker          for (int i = 0; i < 3; i++) {
1427*61046927SAndroid Build Coastguard Worker             gl_prog->info.workgroup_size[i] =
1428*61046927SAndroid Build Coastguard Worker                shader->info.Comp.LocalSize[i];
1429*61046927SAndroid Build Coastguard Worker          }
1430*61046927SAndroid Build Coastguard Worker       } else if (shader->info.Comp.LocalSizeVariable) {
1431*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.workgroup_size[0] != 0) {
1432*61046927SAndroid Build Coastguard Worker             /* The ARB_compute_variable_group_size spec says:
1433*61046927SAndroid Build Coastguard Worker              *
1434*61046927SAndroid Build Coastguard Worker              *     If one compute shader attached to a program declares a
1435*61046927SAndroid Build Coastguard Worker              *     variable local group size and a second compute shader
1436*61046927SAndroid Build Coastguard Worker              *     attached to the same program declares a fixed local group
1437*61046927SAndroid Build Coastguard Worker              *     size, a link-time error results.
1438*61046927SAndroid Build Coastguard Worker              */
1439*61046927SAndroid Build Coastguard Worker             linker_error(prog, "compute shader defined with both fixed and "
1440*61046927SAndroid Build Coastguard Worker                          "variable local group size\n");
1441*61046927SAndroid Build Coastguard Worker             return;
1442*61046927SAndroid Build Coastguard Worker          }
1443*61046927SAndroid Build Coastguard Worker          gl_prog->info.workgroup_size_variable = true;
1444*61046927SAndroid Build Coastguard Worker       }
1445*61046927SAndroid Build Coastguard Worker 
1446*61046927SAndroid Build Coastguard Worker       enum gl_derivative_group group = shader->info.Comp.DerivativeGroup;
1447*61046927SAndroid Build Coastguard Worker       if (group != DERIVATIVE_GROUP_NONE) {
1448*61046927SAndroid Build Coastguard Worker          if (gl_prog->info.derivative_group != DERIVATIVE_GROUP_NONE &&
1449*61046927SAndroid Build Coastguard Worker              gl_prog->info.derivative_group != group) {
1450*61046927SAndroid Build Coastguard Worker             linker_error(prog, "compute shader defined with conflicting "
1451*61046927SAndroid Build Coastguard Worker                          "derivative groups\n");
1452*61046927SAndroid Build Coastguard Worker             return;
1453*61046927SAndroid Build Coastguard Worker          }
1454*61046927SAndroid Build Coastguard Worker          gl_prog->info.derivative_group = group;
1455*61046927SAndroid Build Coastguard Worker       }
1456*61046927SAndroid Build Coastguard Worker    }
1457*61046927SAndroid Build Coastguard Worker 
1458*61046927SAndroid Build Coastguard Worker    /* Just do the intrastage -> interstage propagation right now,
1459*61046927SAndroid Build Coastguard Worker     * since we already know we're in the right type of shader program
1460*61046927SAndroid Build Coastguard Worker     * for doing it.
1461*61046927SAndroid Build Coastguard Worker     */
1462*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.workgroup_size[0] == 0 &&
1463*61046927SAndroid Build Coastguard Worker        !gl_prog->info.workgroup_size_variable) {
1464*61046927SAndroid Build Coastguard Worker       linker_error(prog, "compute shader must contain a fixed or a variable "
1465*61046927SAndroid Build Coastguard Worker                          "local group size\n");
1466*61046927SAndroid Build Coastguard Worker       return;
1467*61046927SAndroid Build Coastguard Worker    }
1468*61046927SAndroid Build Coastguard Worker 
1469*61046927SAndroid Build Coastguard Worker    if (gl_prog->info.derivative_group == DERIVATIVE_GROUP_QUADS) {
1470*61046927SAndroid Build Coastguard Worker       if (gl_prog->info.workgroup_size[0] % 2 != 0) {
1471*61046927SAndroid Build Coastguard Worker          linker_error(prog, "derivative_group_quadsNV must be used with a "
1472*61046927SAndroid Build Coastguard Worker                       "local group size whose first dimension "
1473*61046927SAndroid Build Coastguard Worker                       "is a multiple of 2\n");
1474*61046927SAndroid Build Coastguard Worker          return;
1475*61046927SAndroid Build Coastguard Worker       }
1476*61046927SAndroid Build Coastguard Worker       if (gl_prog->info.workgroup_size[1] % 2 != 0) {
1477*61046927SAndroid Build Coastguard Worker          linker_error(prog, "derivative_group_quadsNV must be used with a local"
1478*61046927SAndroid Build Coastguard Worker                       "group size whose second dimension "
1479*61046927SAndroid Build Coastguard Worker                       "is a multiple of 2\n");
1480*61046927SAndroid Build Coastguard Worker          return;
1481*61046927SAndroid Build Coastguard Worker       }
1482*61046927SAndroid Build Coastguard Worker    } else if (gl_prog->info.derivative_group == DERIVATIVE_GROUP_LINEAR) {
1483*61046927SAndroid Build Coastguard Worker       if ((gl_prog->info.workgroup_size[0] *
1484*61046927SAndroid Build Coastguard Worker            gl_prog->info.workgroup_size[1] *
1485*61046927SAndroid Build Coastguard Worker            gl_prog->info.workgroup_size[2]) % 4 != 0) {
1486*61046927SAndroid Build Coastguard Worker          linker_error(prog, "derivative_group_linearNV must be used with a "
1487*61046927SAndroid Build Coastguard Worker                       "local group size whose total number of invocations "
1488*61046927SAndroid Build Coastguard Worker                       "is a multiple of 4\n");
1489*61046927SAndroid Build Coastguard Worker          return;
1490*61046927SAndroid Build Coastguard Worker       }
1491*61046927SAndroid Build Coastguard Worker    }
1492*61046927SAndroid Build Coastguard Worker }
1493*61046927SAndroid Build Coastguard Worker 
1494*61046927SAndroid Build Coastguard Worker /**
1495*61046927SAndroid Build Coastguard Worker  * Link all out variables on a single stage which are not
1496*61046927SAndroid Build Coastguard Worker  * directly used in a shader with the main function.
1497*61046927SAndroid Build Coastguard Worker  */
1498*61046927SAndroid Build Coastguard Worker static void
link_output_variables(struct gl_linked_shader * linked_shader,struct gl_shader ** shader_list,unsigned num_shaders)1499*61046927SAndroid Build Coastguard Worker link_output_variables(struct gl_linked_shader *linked_shader,
1500*61046927SAndroid Build Coastguard Worker                       struct gl_shader **shader_list,
1501*61046927SAndroid Build Coastguard Worker                       unsigned num_shaders)
1502*61046927SAndroid Build Coastguard Worker {
1503*61046927SAndroid Build Coastguard Worker    struct glsl_symbol_table *symbols = linked_shader->symbols;
1504*61046927SAndroid Build Coastguard Worker 
1505*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1506*61046927SAndroid Build Coastguard Worker 
1507*61046927SAndroid Build Coastguard Worker       /* Skip shader object with main function */
1508*61046927SAndroid Build Coastguard Worker       if (shader_list[i]->symbols->get_function("main"))
1509*61046927SAndroid Build Coastguard Worker          continue;
1510*61046927SAndroid Build Coastguard Worker 
1511*61046927SAndroid Build Coastguard Worker       foreach_in_list(ir_instruction, ir, shader_list[i]->ir) {
1512*61046927SAndroid Build Coastguard Worker          if (ir->ir_type != ir_type_variable)
1513*61046927SAndroid Build Coastguard Worker             continue;
1514*61046927SAndroid Build Coastguard Worker 
1515*61046927SAndroid Build Coastguard Worker          ir_variable *var = (ir_variable *) ir;
1516*61046927SAndroid Build Coastguard Worker 
1517*61046927SAndroid Build Coastguard Worker          if (var->data.mode == ir_var_shader_out &&
1518*61046927SAndroid Build Coastguard Worker                !symbols->get_variable(var->name)) {
1519*61046927SAndroid Build Coastguard Worker             var = var->clone(linked_shader, NULL);
1520*61046927SAndroid Build Coastguard Worker             symbols->add_variable(var);
1521*61046927SAndroid Build Coastguard Worker             linked_shader->ir->push_head(var);
1522*61046927SAndroid Build Coastguard Worker          }
1523*61046927SAndroid Build Coastguard Worker       }
1524*61046927SAndroid Build Coastguard Worker    }
1525*61046927SAndroid Build Coastguard Worker 
1526*61046927SAndroid Build Coastguard Worker    return;
1527*61046927SAndroid Build Coastguard Worker }
1528*61046927SAndroid Build Coastguard Worker 
1529*61046927SAndroid Build Coastguard Worker 
1530*61046927SAndroid Build Coastguard Worker /**
1531*61046927SAndroid Build Coastguard Worker  * Combine a group of shaders for a single stage to generate a linked shader
1532*61046927SAndroid Build Coastguard Worker  *
1533*61046927SAndroid Build Coastguard Worker  * \note
1534*61046927SAndroid Build Coastguard Worker  * If this function is supplied a single shader, it is cloned, and the new
1535*61046927SAndroid Build Coastguard Worker  * shader is returned.
1536*61046927SAndroid Build Coastguard Worker  */
1537*61046927SAndroid Build Coastguard Worker struct gl_linked_shader *
link_intrastage_shaders(void * mem_ctx,struct gl_context * ctx,struct gl_shader_program * prog,struct gl_shader ** shader_list,unsigned num_shaders,bool allow_missing_main)1538*61046927SAndroid Build Coastguard Worker link_intrastage_shaders(void *mem_ctx,
1539*61046927SAndroid Build Coastguard Worker                         struct gl_context *ctx,
1540*61046927SAndroid Build Coastguard Worker                         struct gl_shader_program *prog,
1541*61046927SAndroid Build Coastguard Worker                         struct gl_shader **shader_list,
1542*61046927SAndroid Build Coastguard Worker                         unsigned num_shaders,
1543*61046927SAndroid Build Coastguard Worker                         bool allow_missing_main)
1544*61046927SAndroid Build Coastguard Worker {
1545*61046927SAndroid Build Coastguard Worker    bool arb_fragment_coord_conventions_enable = false;
1546*61046927SAndroid Build Coastguard Worker    bool KHR_shader_subgroup_basic_enable = false;
1547*61046927SAndroid Build Coastguard Worker 
1548*61046927SAndroid Build Coastguard Worker    /* Check that global variables defined in multiple shaders are consistent.
1549*61046927SAndroid Build Coastguard Worker     */
1550*61046927SAndroid Build Coastguard Worker    glsl_symbol_table variables;
1551*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1552*61046927SAndroid Build Coastguard Worker       if (shader_list[i] == NULL)
1553*61046927SAndroid Build Coastguard Worker          continue;
1554*61046927SAndroid Build Coastguard Worker       cross_validate_globals(&ctx->Const, prog, shader_list[i]->ir, &variables,
1555*61046927SAndroid Build Coastguard Worker                              false);
1556*61046927SAndroid Build Coastguard Worker       if (shader_list[i]->ARB_fragment_coord_conventions_enable)
1557*61046927SAndroid Build Coastguard Worker          arb_fragment_coord_conventions_enable = true;
1558*61046927SAndroid Build Coastguard Worker       if (shader_list[i]->KHR_shader_subgroup_basic_enable)
1559*61046927SAndroid Build Coastguard Worker          KHR_shader_subgroup_basic_enable = true;
1560*61046927SAndroid Build Coastguard Worker    }
1561*61046927SAndroid Build Coastguard Worker 
1562*61046927SAndroid Build Coastguard Worker    if (!prog->data->LinkStatus)
1563*61046927SAndroid Build Coastguard Worker       return NULL;
1564*61046927SAndroid Build Coastguard Worker 
1565*61046927SAndroid Build Coastguard Worker    /* Check that interface blocks defined in multiple shaders are consistent.
1566*61046927SAndroid Build Coastguard Worker     */
1567*61046927SAndroid Build Coastguard Worker    validate_intrastage_interface_blocks(prog, (const gl_shader **)shader_list,
1568*61046927SAndroid Build Coastguard Worker                                         num_shaders);
1569*61046927SAndroid Build Coastguard Worker    if (!prog->data->LinkStatus)
1570*61046927SAndroid Build Coastguard Worker       return NULL;
1571*61046927SAndroid Build Coastguard Worker 
1572*61046927SAndroid Build Coastguard Worker    /* Check that there is only a single definition of each function signature
1573*61046927SAndroid Build Coastguard Worker     * across all shaders.
1574*61046927SAndroid Build Coastguard Worker     */
1575*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < (num_shaders - 1); i++) {
1576*61046927SAndroid Build Coastguard Worker       foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
1577*61046927SAndroid Build Coastguard Worker          ir_function *const f = node->as_function();
1578*61046927SAndroid Build Coastguard Worker 
1579*61046927SAndroid Build Coastguard Worker          if (f == NULL)
1580*61046927SAndroid Build Coastguard Worker             continue;
1581*61046927SAndroid Build Coastguard Worker 
1582*61046927SAndroid Build Coastguard Worker          for (unsigned j = i + 1; j < num_shaders; j++) {
1583*61046927SAndroid Build Coastguard Worker             ir_function *const other =
1584*61046927SAndroid Build Coastguard Worker                shader_list[j]->symbols->get_function(f->name);
1585*61046927SAndroid Build Coastguard Worker 
1586*61046927SAndroid Build Coastguard Worker             /* If the other shader has no function (and therefore no function
1587*61046927SAndroid Build Coastguard Worker              * signatures) with the same name, skip to the next shader.
1588*61046927SAndroid Build Coastguard Worker              */
1589*61046927SAndroid Build Coastguard Worker             if (other == NULL)
1590*61046927SAndroid Build Coastguard Worker                continue;
1591*61046927SAndroid Build Coastguard Worker 
1592*61046927SAndroid Build Coastguard Worker             foreach_in_list(ir_function_signature, sig, &f->signatures) {
1593*61046927SAndroid Build Coastguard Worker                if (!sig->is_defined)
1594*61046927SAndroid Build Coastguard Worker                   continue;
1595*61046927SAndroid Build Coastguard Worker 
1596*61046927SAndroid Build Coastguard Worker                ir_function_signature *other_sig =
1597*61046927SAndroid Build Coastguard Worker                   other->exact_matching_signature(NULL, &sig->parameters);
1598*61046927SAndroid Build Coastguard Worker 
1599*61046927SAndroid Build Coastguard Worker                if (other_sig != NULL && other_sig->is_defined) {
1600*61046927SAndroid Build Coastguard Worker                   linker_error(prog, "function `%s' is multiply defined\n",
1601*61046927SAndroid Build Coastguard Worker                                f->name);
1602*61046927SAndroid Build Coastguard Worker                   return NULL;
1603*61046927SAndroid Build Coastguard Worker                }
1604*61046927SAndroid Build Coastguard Worker             }
1605*61046927SAndroid Build Coastguard Worker          }
1606*61046927SAndroid Build Coastguard Worker       }
1607*61046927SAndroid Build Coastguard Worker    }
1608*61046927SAndroid Build Coastguard Worker 
1609*61046927SAndroid Build Coastguard Worker    /* Find the shader that defines main, and make a clone of it.
1610*61046927SAndroid Build Coastguard Worker     *
1611*61046927SAndroid Build Coastguard Worker     * Starting with the clone, search for undefined references.  If one is
1612*61046927SAndroid Build Coastguard Worker     * found, find the shader that defines it.  Clone the reference and add
1613*61046927SAndroid Build Coastguard Worker     * it to the shader.  Repeat until there are no undefined references or
1614*61046927SAndroid Build Coastguard Worker     * until a reference cannot be resolved.
1615*61046927SAndroid Build Coastguard Worker     */
1616*61046927SAndroid Build Coastguard Worker    gl_shader *main = NULL;
1617*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < num_shaders; i++) {
1618*61046927SAndroid Build Coastguard Worker       if (_mesa_get_main_function_signature(shader_list[i]->symbols)) {
1619*61046927SAndroid Build Coastguard Worker          main = shader_list[i];
1620*61046927SAndroid Build Coastguard Worker          break;
1621*61046927SAndroid Build Coastguard Worker       }
1622*61046927SAndroid Build Coastguard Worker    }
1623*61046927SAndroid Build Coastguard Worker 
1624*61046927SAndroid Build Coastguard Worker    if (main == NULL && allow_missing_main)
1625*61046927SAndroid Build Coastguard Worker       main = shader_list[0];
1626*61046927SAndroid Build Coastguard Worker 
1627*61046927SAndroid Build Coastguard Worker    if (main == NULL) {
1628*61046927SAndroid Build Coastguard Worker       linker_error(prog, "%s shader lacks `main'\n",
1629*61046927SAndroid Build Coastguard Worker                    _mesa_shader_stage_to_string(shader_list[0]->Stage));
1630*61046927SAndroid Build Coastguard Worker       return NULL;
1631*61046927SAndroid Build Coastguard Worker    }
1632*61046927SAndroid Build Coastguard Worker 
1633*61046927SAndroid Build Coastguard Worker    gl_linked_shader *linked = rzalloc(NULL, struct gl_linked_shader);
1634*61046927SAndroid Build Coastguard Worker    linked->Stage = shader_list[0]->Stage;
1635*61046927SAndroid Build Coastguard Worker 
1636*61046927SAndroid Build Coastguard Worker    /* Create program and attach it to the linked shader */
1637*61046927SAndroid Build Coastguard Worker    struct gl_program *gl_prog =
1638*61046927SAndroid Build Coastguard Worker       ctx->Driver.NewProgram(ctx, shader_list[0]->Stage, prog->Name, false);
1639*61046927SAndroid Build Coastguard Worker    if (!gl_prog) {
1640*61046927SAndroid Build Coastguard Worker       prog->data->LinkStatus = LINKING_FAILURE;
1641*61046927SAndroid Build Coastguard Worker       _mesa_delete_linked_shader(ctx, linked);
1642*61046927SAndroid Build Coastguard Worker       return NULL;
1643*61046927SAndroid Build Coastguard Worker    }
1644*61046927SAndroid Build Coastguard Worker 
1645*61046927SAndroid Build Coastguard Worker    _mesa_reference_shader_program_data(&gl_prog->sh.data, prog->data);
1646*61046927SAndroid Build Coastguard Worker 
1647*61046927SAndroid Build Coastguard Worker    /* Don't use _mesa_reference_program() just take ownership */
1648*61046927SAndroid Build Coastguard Worker    linked->Program = gl_prog;
1649*61046927SAndroid Build Coastguard Worker 
1650*61046927SAndroid Build Coastguard Worker    linked->ir = new(linked) exec_list;
1651*61046927SAndroid Build Coastguard Worker    clone_ir_list(mem_ctx, linked->ir, main->ir);
1652*61046927SAndroid Build Coastguard Worker 
1653*61046927SAndroid Build Coastguard Worker    link_fs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders,
1654*61046927SAndroid Build Coastguard Worker                                    arb_fragment_coord_conventions_enable);
1655*61046927SAndroid Build Coastguard Worker    link_tcs_out_layout_qualifiers(prog, gl_prog, shader_list, num_shaders);
1656*61046927SAndroid Build Coastguard Worker    link_tes_in_layout_qualifiers(prog, gl_prog, shader_list, num_shaders);
1657*61046927SAndroid Build Coastguard Worker    link_gs_inout_layout_qualifiers(prog, gl_prog, shader_list, num_shaders);
1658*61046927SAndroid Build Coastguard Worker    link_cs_input_layout_qualifiers(prog, gl_prog, shader_list, num_shaders);
1659*61046927SAndroid Build Coastguard Worker 
1660*61046927SAndroid Build Coastguard Worker    if (linked->Stage != MESA_SHADER_FRAGMENT)
1661*61046927SAndroid Build Coastguard Worker       link_xfb_stride_layout_qualifiers(&ctx->Const, prog, shader_list, num_shaders);
1662*61046927SAndroid Build Coastguard Worker 
1663*61046927SAndroid Build Coastguard Worker    link_bindless_layout_qualifiers(prog, shader_list, num_shaders);
1664*61046927SAndroid Build Coastguard Worker 
1665*61046927SAndroid Build Coastguard Worker    link_layer_viewport_relative_qualifier(prog, gl_prog, shader_list, num_shaders);
1666*61046927SAndroid Build Coastguard Worker 
1667*61046927SAndroid Build Coastguard Worker    populate_symbol_table(linked, shader_list[0]->symbols);
1668*61046927SAndroid Build Coastguard Worker 
1669*61046927SAndroid Build Coastguard Worker    gl_prog->info.subgroup_size = KHR_shader_subgroup_basic_enable ?
1670*61046927SAndroid Build Coastguard Worker       SUBGROUP_SIZE_API_CONSTANT : SUBGROUP_SIZE_UNIFORM;
1671*61046927SAndroid Build Coastguard Worker 
1672*61046927SAndroid Build Coastguard Worker    /* The pointer to the main function in the final linked shader (i.e., the
1673*61046927SAndroid Build Coastguard Worker     * copy of the original shader that contained the main function).
1674*61046927SAndroid Build Coastguard Worker     */
1675*61046927SAndroid Build Coastguard Worker    ir_function_signature *const main_sig =
1676*61046927SAndroid Build Coastguard Worker       _mesa_get_main_function_signature(linked->symbols);
1677*61046927SAndroid Build Coastguard Worker 
1678*61046927SAndroid Build Coastguard Worker    /* Move any instructions other than variable declarations or function
1679*61046927SAndroid Build Coastguard Worker     * declarations into main.
1680*61046927SAndroid Build Coastguard Worker     */
1681*61046927SAndroid Build Coastguard Worker    if (main_sig != NULL) {
1682*61046927SAndroid Build Coastguard Worker       exec_node *insertion_point =
1683*61046927SAndroid Build Coastguard Worker          move_non_declarations(linked->ir, &main_sig->body.head_sentinel, false,
1684*61046927SAndroid Build Coastguard Worker                                linked);
1685*61046927SAndroid Build Coastguard Worker 
1686*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_shaders; i++) {
1687*61046927SAndroid Build Coastguard Worker          if (shader_list[i] == main)
1688*61046927SAndroid Build Coastguard Worker             continue;
1689*61046927SAndroid Build Coastguard Worker 
1690*61046927SAndroid Build Coastguard Worker          insertion_point = move_non_declarations(shader_list[i]->ir,
1691*61046927SAndroid Build Coastguard Worker                                                  insertion_point, true, linked);
1692*61046927SAndroid Build Coastguard Worker       }
1693*61046927SAndroid Build Coastguard Worker    }
1694*61046927SAndroid Build Coastguard Worker 
1695*61046927SAndroid Build Coastguard Worker    if (!link_function_calls(prog, linked, main, shader_list, num_shaders)) {
1696*61046927SAndroid Build Coastguard Worker       _mesa_delete_linked_shader(ctx, linked);
1697*61046927SAndroid Build Coastguard Worker       return NULL;
1698*61046927SAndroid Build Coastguard Worker    }
1699*61046927SAndroid Build Coastguard Worker 
1700*61046927SAndroid Build Coastguard Worker    if (linked->Stage != MESA_SHADER_FRAGMENT)
1701*61046927SAndroid Build Coastguard Worker       link_output_variables(linked, shader_list, num_shaders);
1702*61046927SAndroid Build Coastguard Worker 
1703*61046927SAndroid Build Coastguard Worker    /* Make a pass over all variable declarations to ensure that arrays with
1704*61046927SAndroid Build Coastguard Worker     * unspecified sizes have a size specified.  The size is inferred from the
1705*61046927SAndroid Build Coastguard Worker     * max_array_access field.
1706*61046927SAndroid Build Coastguard Worker     */
1707*61046927SAndroid Build Coastguard Worker    array_sizing_visitor v;
1708*61046927SAndroid Build Coastguard Worker    v.run(linked->ir);
1709*61046927SAndroid Build Coastguard Worker    v.fixup_unnamed_interface_types();
1710*61046927SAndroid Build Coastguard Worker 
1711*61046927SAndroid Build Coastguard Worker    /* Now that we know the sizes of all the arrays, we can replace .length()
1712*61046927SAndroid Build Coastguard Worker     * calls with a constant expression.
1713*61046927SAndroid Build Coastguard Worker     */
1714*61046927SAndroid Build Coastguard Worker    array_length_to_const_visitor len_v;
1715*61046927SAndroid Build Coastguard Worker    len_v.run(linked->ir);
1716*61046927SAndroid Build Coastguard Worker 
1717*61046927SAndroid Build Coastguard Worker    if (!prog->data->LinkStatus) {
1718*61046927SAndroid Build Coastguard Worker       _mesa_delete_linked_shader(ctx, linked);
1719*61046927SAndroid Build Coastguard Worker       return NULL;
1720*61046927SAndroid Build Coastguard Worker    }
1721*61046927SAndroid Build Coastguard Worker 
1722*61046927SAndroid Build Coastguard Worker    /* At this point linked should contain all of the linked IR, so
1723*61046927SAndroid Build Coastguard Worker     * validate it to make sure nothing went wrong.
1724*61046927SAndroid Build Coastguard Worker     */
1725*61046927SAndroid Build Coastguard Worker    validate_ir_tree(linked->ir);
1726*61046927SAndroid Build Coastguard Worker 
1727*61046927SAndroid Build Coastguard Worker    /* Set the linked source BLAKE3. */
1728*61046927SAndroid Build Coastguard Worker    if (num_shaders == 1) {
1729*61046927SAndroid Build Coastguard Worker       memcpy(linked->linked_source_blake3, shader_list[0]->compiled_source_blake3,
1730*61046927SAndroid Build Coastguard Worker              BLAKE3_OUT_LEN);
1731*61046927SAndroid Build Coastguard Worker    } else {
1732*61046927SAndroid Build Coastguard Worker       struct mesa_blake3 blake3_ctx;
1733*61046927SAndroid Build Coastguard Worker       _mesa_blake3_init(&blake3_ctx);
1734*61046927SAndroid Build Coastguard Worker 
1735*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < num_shaders; i++) {
1736*61046927SAndroid Build Coastguard Worker          if (shader_list[i] == NULL)
1737*61046927SAndroid Build Coastguard Worker             continue;
1738*61046927SAndroid Build Coastguard Worker 
1739*61046927SAndroid Build Coastguard Worker          _mesa_blake3_update(&blake3_ctx, shader_list[i]->compiled_source_blake3,
1740*61046927SAndroid Build Coastguard Worker                              BLAKE3_OUT_LEN);
1741*61046927SAndroid Build Coastguard Worker       }
1742*61046927SAndroid Build Coastguard Worker       _mesa_blake3_final(&blake3_ctx, linked->linked_source_blake3);
1743*61046927SAndroid Build Coastguard Worker    }
1744*61046927SAndroid Build Coastguard Worker 
1745*61046927SAndroid Build Coastguard Worker    return linked;
1746*61046927SAndroid Build Coastguard Worker }
1747*61046927SAndroid Build Coastguard Worker 
1748*61046927SAndroid Build Coastguard Worker void
link_shaders(struct gl_context * ctx,struct gl_shader_program * prog)1749*61046927SAndroid Build Coastguard Worker link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
1750*61046927SAndroid Build Coastguard Worker {
1751*61046927SAndroid Build Coastguard Worker    const struct gl_constants *consts = &ctx->Const;
1752*61046927SAndroid Build Coastguard Worker    prog->data->LinkStatus = LINKING_SUCCESS; /* All error paths will set this to false */
1753*61046927SAndroid Build Coastguard Worker    prog->data->Validated = false;
1754*61046927SAndroid Build Coastguard Worker 
1755*61046927SAndroid Build Coastguard Worker    /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec says:
1756*61046927SAndroid Build Coastguard Worker     *
1757*61046927SAndroid Build Coastguard Worker     *     "Linking can fail for a variety of reasons as specified in the
1758*61046927SAndroid Build Coastguard Worker     *     OpenGL Shading Language Specification, as well as any of the
1759*61046927SAndroid Build Coastguard Worker     *     following reasons:
1760*61046927SAndroid Build Coastguard Worker     *
1761*61046927SAndroid Build Coastguard Worker     *     - No shader objects are attached to program."
1762*61046927SAndroid Build Coastguard Worker     *
1763*61046927SAndroid Build Coastguard Worker     * The Compatibility Profile specification does not list the error.  In
1764*61046927SAndroid Build Coastguard Worker     * Compatibility Profile missing shader stages are replaced by
1765*61046927SAndroid Build Coastguard Worker     * fixed-function.  This applies to the case where all stages are
1766*61046927SAndroid Build Coastguard Worker     * missing.
1767*61046927SAndroid Build Coastguard Worker     */
1768*61046927SAndroid Build Coastguard Worker    if (prog->NumShaders == 0) {
1769*61046927SAndroid Build Coastguard Worker       if (ctx->API != API_OPENGL_COMPAT)
1770*61046927SAndroid Build Coastguard Worker          linker_error(prog, "no shaders attached to the program\n");
1771*61046927SAndroid Build Coastguard Worker       return;
1772*61046927SAndroid Build Coastguard Worker    }
1773*61046927SAndroid Build Coastguard Worker 
1774*61046927SAndroid Build Coastguard Worker #ifdef ENABLE_SHADER_CACHE
1775*61046927SAndroid Build Coastguard Worker    if (shader_cache_read_program_metadata(ctx, prog))
1776*61046927SAndroid Build Coastguard Worker       return;
1777*61046927SAndroid Build Coastguard Worker #endif
1778*61046927SAndroid Build Coastguard Worker 
1779*61046927SAndroid Build Coastguard Worker    void *mem_ctx = ralloc_context(NULL); // temporary linker context
1780*61046927SAndroid Build Coastguard Worker 
1781*61046927SAndroid Build Coastguard Worker    /* Separate the shaders into groups based on their type.
1782*61046927SAndroid Build Coastguard Worker     */
1783*61046927SAndroid Build Coastguard Worker    struct gl_shader **shader_list[MESA_SHADER_STAGES];
1784*61046927SAndroid Build Coastguard Worker    unsigned num_shaders[MESA_SHADER_STAGES];
1785*61046927SAndroid Build Coastguard Worker 
1786*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < MESA_SHADER_STAGES; i++) {
1787*61046927SAndroid Build Coastguard Worker       shader_list[i] = (struct gl_shader **)
1788*61046927SAndroid Build Coastguard Worker          calloc(prog->NumShaders, sizeof(struct gl_shader *));
1789*61046927SAndroid Build Coastguard Worker       num_shaders[i] = 0;
1790*61046927SAndroid Build Coastguard Worker    }
1791*61046927SAndroid Build Coastguard Worker 
1792*61046927SAndroid Build Coastguard Worker    unsigned min_version = UINT_MAX;
1793*61046927SAndroid Build Coastguard Worker    unsigned max_version = 0;
1794*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < prog->NumShaders; i++) {
1795*61046927SAndroid Build Coastguard Worker       min_version = MIN2(min_version, prog->Shaders[i]->Version);
1796*61046927SAndroid Build Coastguard Worker       max_version = MAX2(max_version, prog->Shaders[i]->Version);
1797*61046927SAndroid Build Coastguard Worker 
1798*61046927SAndroid Build Coastguard Worker       if (!consts->AllowGLSLRelaxedES &&
1799*61046927SAndroid Build Coastguard Worker           prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) {
1800*61046927SAndroid Build Coastguard Worker          linker_error(prog, "all shaders must use same shading "
1801*61046927SAndroid Build Coastguard Worker                       "language version\n");
1802*61046927SAndroid Build Coastguard Worker          goto done;
1803*61046927SAndroid Build Coastguard Worker       }
1804*61046927SAndroid Build Coastguard Worker 
1805*61046927SAndroid Build Coastguard Worker       gl_shader_stage shader_type = prog->Shaders[i]->Stage;
1806*61046927SAndroid Build Coastguard Worker       shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i];
1807*61046927SAndroid Build Coastguard Worker       num_shaders[shader_type]++;
1808*61046927SAndroid Build Coastguard Worker    }
1809*61046927SAndroid Build Coastguard Worker 
1810*61046927SAndroid Build Coastguard Worker    /* In desktop GLSL, different shader versions may be linked together.  In
1811*61046927SAndroid Build Coastguard Worker     * GLSL ES, all shader versions must be the same.
1812*61046927SAndroid Build Coastguard Worker     */
1813*61046927SAndroid Build Coastguard Worker    if (!consts->AllowGLSLRelaxedES && prog->Shaders[0]->IsES &&
1814*61046927SAndroid Build Coastguard Worker        min_version != max_version) {
1815*61046927SAndroid Build Coastguard Worker       linker_error(prog, "all shaders must use same shading "
1816*61046927SAndroid Build Coastguard Worker                    "language version\n");
1817*61046927SAndroid Build Coastguard Worker       goto done;
1818*61046927SAndroid Build Coastguard Worker    }
1819*61046927SAndroid Build Coastguard Worker 
1820*61046927SAndroid Build Coastguard Worker    prog->GLSL_Version = max_version;
1821*61046927SAndroid Build Coastguard Worker    prog->IsES = prog->Shaders[0]->IsES;
1822*61046927SAndroid Build Coastguard Worker 
1823*61046927SAndroid Build Coastguard Worker    /* Some shaders have to be linked with some other shaders present.
1824*61046927SAndroid Build Coastguard Worker     */
1825*61046927SAndroid Build Coastguard Worker    if (!prog->SeparateShader) {
1826*61046927SAndroid Build Coastguard Worker       if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
1827*61046927SAndroid Build Coastguard Worker           num_shaders[MESA_SHADER_VERTEX] == 0) {
1828*61046927SAndroid Build Coastguard Worker          linker_error(prog, "Geometry shader must be linked with "
1829*61046927SAndroid Build Coastguard Worker                       "vertex shader\n");
1830*61046927SAndroid Build Coastguard Worker          goto done;
1831*61046927SAndroid Build Coastguard Worker       }
1832*61046927SAndroid Build Coastguard Worker       if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 &&
1833*61046927SAndroid Build Coastguard Worker           num_shaders[MESA_SHADER_VERTEX] == 0) {
1834*61046927SAndroid Build Coastguard Worker          linker_error(prog, "Tessellation evaluation shader must be linked "
1835*61046927SAndroid Build Coastguard Worker                       "with vertex shader\n");
1836*61046927SAndroid Build Coastguard Worker          goto done;
1837*61046927SAndroid Build Coastguard Worker       }
1838*61046927SAndroid Build Coastguard Worker       if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
1839*61046927SAndroid Build Coastguard Worker           num_shaders[MESA_SHADER_VERTEX] == 0) {
1840*61046927SAndroid Build Coastguard Worker          linker_error(prog, "Tessellation control shader must be linked with "
1841*61046927SAndroid Build Coastguard Worker                       "vertex shader\n");
1842*61046927SAndroid Build Coastguard Worker          goto done;
1843*61046927SAndroid Build Coastguard Worker       }
1844*61046927SAndroid Build Coastguard Worker 
1845*61046927SAndroid Build Coastguard Worker       /* Section 7.3 of the OpenGL ES 3.2 specification says:
1846*61046927SAndroid Build Coastguard Worker        *
1847*61046927SAndroid Build Coastguard Worker        *    "Linking can fail for [...] any of the following reasons:
1848*61046927SAndroid Build Coastguard Worker        *
1849*61046927SAndroid Build Coastguard Worker        *     * program contains an object to form a tessellation control
1850*61046927SAndroid Build Coastguard Worker        *       shader [...] and [...] the program is not separable and
1851*61046927SAndroid Build Coastguard Worker        *       contains no object to form a tessellation evaluation shader"
1852*61046927SAndroid Build Coastguard Worker        *
1853*61046927SAndroid Build Coastguard Worker        * The OpenGL spec is contradictory. It allows linking without a tess
1854*61046927SAndroid Build Coastguard Worker        * eval shader, but that can only be used with transform feedback and
1855*61046927SAndroid Build Coastguard Worker        * rasterization disabled. However, transform feedback isn't allowed
1856*61046927SAndroid Build Coastguard Worker        * with GL_PATCHES, so it can't be used.
1857*61046927SAndroid Build Coastguard Worker        *
1858*61046927SAndroid Build Coastguard Worker        * More investigation showed that the idea of transform feedback after
1859*61046927SAndroid Build Coastguard Worker        * a tess control shader was dropped, because some hw vendors couldn't
1860*61046927SAndroid Build Coastguard Worker        * support tessellation without a tess eval shader, but the linker
1861*61046927SAndroid Build Coastguard Worker        * section wasn't updated to reflect that.
1862*61046927SAndroid Build Coastguard Worker        *
1863*61046927SAndroid Build Coastguard Worker        * All specifications (ARB_tessellation_shader, GL 4.0-4.5) have this
1864*61046927SAndroid Build Coastguard Worker        * spec bug.
1865*61046927SAndroid Build Coastguard Worker        *
1866*61046927SAndroid Build Coastguard Worker        * Do what's reasonable and always require a tess eval shader if a tess
1867*61046927SAndroid Build Coastguard Worker        * control shader is present.
1868*61046927SAndroid Build Coastguard Worker        */
1869*61046927SAndroid Build Coastguard Worker       if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
1870*61046927SAndroid Build Coastguard Worker           num_shaders[MESA_SHADER_TESS_EVAL] == 0) {
1871*61046927SAndroid Build Coastguard Worker          linker_error(prog, "Tessellation control shader must be linked with "
1872*61046927SAndroid Build Coastguard Worker                       "tessellation evaluation shader\n");
1873*61046927SAndroid Build Coastguard Worker          goto done;
1874*61046927SAndroid Build Coastguard Worker       }
1875*61046927SAndroid Build Coastguard Worker 
1876*61046927SAndroid Build Coastguard Worker       if (prog->IsES) {
1877*61046927SAndroid Build Coastguard Worker          if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 &&
1878*61046927SAndroid Build Coastguard Worker              num_shaders[MESA_SHADER_TESS_CTRL] == 0) {
1879*61046927SAndroid Build Coastguard Worker             linker_error(prog, "GLSL ES requires non-separable programs "
1880*61046927SAndroid Build Coastguard Worker                          "containing a tessellation evaluation shader to also "
1881*61046927SAndroid Build Coastguard Worker                          "be linked with a tessellation control shader\n");
1882*61046927SAndroid Build Coastguard Worker             goto done;
1883*61046927SAndroid Build Coastguard Worker          }
1884*61046927SAndroid Build Coastguard Worker       }
1885*61046927SAndroid Build Coastguard Worker    }
1886*61046927SAndroid Build Coastguard Worker 
1887*61046927SAndroid Build Coastguard Worker    /* Compute shaders have additional restrictions. */
1888*61046927SAndroid Build Coastguard Worker    if (num_shaders[MESA_SHADER_COMPUTE] > 0 &&
1889*61046927SAndroid Build Coastguard Worker        num_shaders[MESA_SHADER_COMPUTE] != prog->NumShaders) {
1890*61046927SAndroid Build Coastguard Worker       linker_error(prog, "Compute shaders may not be linked with any other "
1891*61046927SAndroid Build Coastguard Worker                    "type of shader\n");
1892*61046927SAndroid Build Coastguard Worker    }
1893*61046927SAndroid Build Coastguard Worker 
1894*61046927SAndroid Build Coastguard Worker    /* Link all shaders for a particular stage and validate the result.
1895*61046927SAndroid Build Coastguard Worker     */
1896*61046927SAndroid Build Coastguard Worker    for (int stage = 0; stage < MESA_SHADER_STAGES; stage++) {
1897*61046927SAndroid Build Coastguard Worker       if (num_shaders[stage] > 0) {
1898*61046927SAndroid Build Coastguard Worker          gl_linked_shader *const sh =
1899*61046927SAndroid Build Coastguard Worker             link_intrastage_shaders(mem_ctx, ctx, prog, shader_list[stage],
1900*61046927SAndroid Build Coastguard Worker                                     num_shaders[stage], false);
1901*61046927SAndroid Build Coastguard Worker 
1902*61046927SAndroid Build Coastguard Worker          if (!prog->data->LinkStatus) {
1903*61046927SAndroid Build Coastguard Worker             if (sh)
1904*61046927SAndroid Build Coastguard Worker                _mesa_delete_linked_shader(ctx, sh);
1905*61046927SAndroid Build Coastguard Worker             goto done;
1906*61046927SAndroid Build Coastguard Worker          }
1907*61046927SAndroid Build Coastguard Worker 
1908*61046927SAndroid Build Coastguard Worker          prog->_LinkedShaders[stage] = sh;
1909*61046927SAndroid Build Coastguard Worker          prog->data->linked_stages |= 1 << stage;
1910*61046927SAndroid Build Coastguard Worker       }
1911*61046927SAndroid Build Coastguard Worker    }
1912*61046927SAndroid Build Coastguard Worker 
1913*61046927SAndroid Build Coastguard Worker done:
1914*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
1915*61046927SAndroid Build Coastguard Worker       free(shader_list[i]);
1916*61046927SAndroid Build Coastguard Worker       if (prog->_LinkedShaders[i] == NULL)
1917*61046927SAndroid Build Coastguard Worker          continue;
1918*61046927SAndroid Build Coastguard Worker 
1919*61046927SAndroid Build Coastguard Worker       /* Do a final validation step to make sure that the IR wasn't
1920*61046927SAndroid Build Coastguard Worker        * invalidated by any modifications performed after intrastage linking.
1921*61046927SAndroid Build Coastguard Worker        */
1922*61046927SAndroid Build Coastguard Worker       validate_ir_tree(prog->_LinkedShaders[i]->ir);
1923*61046927SAndroid Build Coastguard Worker 
1924*61046927SAndroid Build Coastguard Worker       /* Retain any live IR, but trash the rest. */
1925*61046927SAndroid Build Coastguard Worker       reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir);
1926*61046927SAndroid Build Coastguard Worker 
1927*61046927SAndroid Build Coastguard Worker       /* The symbol table in the linked shaders may contain references to
1928*61046927SAndroid Build Coastguard Worker        * variables that were removed (e.g., unused uniforms).  Since it may
1929*61046927SAndroid Build Coastguard Worker        * contain junk, there is no possible valid use.  Delete it and set the
1930*61046927SAndroid Build Coastguard Worker        * pointer to NULL.
1931*61046927SAndroid Build Coastguard Worker        */
1932*61046927SAndroid Build Coastguard Worker       delete prog->_LinkedShaders[i]->symbols;
1933*61046927SAndroid Build Coastguard Worker       prog->_LinkedShaders[i]->symbols = NULL;
1934*61046927SAndroid Build Coastguard Worker    }
1935*61046927SAndroid Build Coastguard Worker 
1936*61046927SAndroid Build Coastguard Worker    ralloc_free(mem_ctx);
1937*61046927SAndroid Build Coastguard Worker }
1938*61046927SAndroid Build Coastguard Worker 
1939*61046927SAndroid Build Coastguard Worker void
resource_name_updated(struct gl_resource_name * name)1940*61046927SAndroid Build Coastguard Worker resource_name_updated(struct gl_resource_name *name)
1941*61046927SAndroid Build Coastguard Worker {
1942*61046927SAndroid Build Coastguard Worker    if (name->string) {
1943*61046927SAndroid Build Coastguard Worker       name->length = strlen(name->string);
1944*61046927SAndroid Build Coastguard Worker 
1945*61046927SAndroid Build Coastguard Worker       const char *last_square_bracket = strrchr(name->string, '[');
1946*61046927SAndroid Build Coastguard Worker       if (last_square_bracket) {
1947*61046927SAndroid Build Coastguard Worker          name->last_square_bracket = last_square_bracket - name->string;
1948*61046927SAndroid Build Coastguard Worker          name->suffix_is_zero_square_bracketed =
1949*61046927SAndroid Build Coastguard Worker             strcmp(last_square_bracket, "[0]") == 0;
1950*61046927SAndroid Build Coastguard Worker       } else {
1951*61046927SAndroid Build Coastguard Worker          name->last_square_bracket = -1;
1952*61046927SAndroid Build Coastguard Worker          name->suffix_is_zero_square_bracketed = false;
1953*61046927SAndroid Build Coastguard Worker       }
1954*61046927SAndroid Build Coastguard Worker    } else {
1955*61046927SAndroid Build Coastguard Worker       name->length = 0;
1956*61046927SAndroid Build Coastguard Worker       name->last_square_bracket = -1;
1957*61046927SAndroid Build Coastguard Worker       name->suffix_is_zero_square_bracketed = false;
1958*61046927SAndroid Build Coastguard Worker    }
1959*61046927SAndroid Build Coastguard Worker }
1960