xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/gl_nir_link_interface_blocks.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2013 Intel Corporation
3  * Copyright © 2024 Valve Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * Linker support for GLSL's interface blocks.
27  */
28 
29 #include "gl_nir_linker.h"
30 #include "linker_util.h"
31 #include "nir.h"
32 #include "main/macros.h"
33 #include "main/shader_types.h"
34 #include "util/hash_table.h"
35 #include "util/u_string.h"
36 
37 
38 /**
39  * Return true if interface members mismatch and its not allowed by GLSL.
40  */
41 static bool
interstage_member_mismatch(struct gl_shader_program * prog,const struct glsl_type * c,const struct glsl_type * p)42 interstage_member_mismatch(struct gl_shader_program *prog,
43                            const struct glsl_type *c,
44                            const struct glsl_type *p)
45 {
46    if (c->length != p->length)
47       return true;
48 
49    for (unsigned i = 0; i < c->length; i++) {
50       if (c->fields.structure[i].type != p->fields.structure[i].type)
51          return true;
52       if (strcmp(c->fields.structure[i].name,
53                  p->fields.structure[i].name) != 0)
54          return true;
55       if (c->fields.structure[i].location !=
56           p->fields.structure[i].location)
57          return true;
58       if (c->fields.structure[i].component !=
59           p->fields.structure[i].component)
60          return true;
61       if (c->fields.structure[i].patch !=
62           p->fields.structure[i].patch)
63          return true;
64 
65       /* From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.40 spec:
66        *
67        *    "It is a link-time error if, within the same stage, the
68        *    interpolation qualifiers of variables of the same name do not
69        *    match."
70        */
71       if (prog->IsES || prog->GLSL_Version < 440)
72          if (c->fields.structure[i].interpolation !=
73              p->fields.structure[i].interpolation)
74             return true;
75 
76       /* From Section 4.3.4 (Input Variables) of the GLSL ES 3.0 spec:
77        *
78        *    "The output of the vertex shader and the input of the fragment
79        *    shader form an interface.  For this interface, vertex shader
80        *    output variables and fragment shader input variables of the same
81        *    name must match in type and qualification (other than precision
82        *    and out matching to in).
83        *
84        * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.1 spec
85        * says that centroid no longer needs to match for varyings.
86        *
87        * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.2 spec
88        * says that sample need not match for varyings.
89        */
90       if (!prog->IsES || prog->GLSL_Version < 310)
91          if (c->fields.structure[i].centroid !=
92              p->fields.structure[i].centroid)
93             return true;
94       if (!prog->IsES)
95          if (c->fields.structure[i].sample !=
96              p->fields.structure[i].sample)
97             return true;
98    }
99 
100    return false;
101 }
102 
103 static bool
is_interface_instance(nir_variable * var)104 is_interface_instance(nir_variable *var)
105 {
106  return glsl_without_array(var->type) == var->interface_type;
107 }
108 
109 /**
110  * Check if two interfaces match, according to intrastage interface matching
111  * rules.  If they do, and the first interface uses an unsized array, it will
112  * be updated to reflect the array size declared in the second interface.
113  */
114 static bool
intrastage_match(nir_variable * a,nir_variable * b,struct gl_shader_program * prog,unsigned a_stage,bool match_precision)115 intrastage_match(nir_variable *a,
116                  nir_variable *b,
117                  struct gl_shader_program *prog,
118                  unsigned a_stage,
119                  bool match_precision)
120 {
121    /* From section 4.7 "Precision and Precision Qualifiers" in GLSL 4.50:
122     *
123     *    "For the purposes of determining if an output from one shader
124     *    stage matches an input of the next stage, the precision qualifier
125     *    need not match."
126     */
127    bool interface_type_match =
128       (prog->IsES ? a->interface_type == b->interface_type :
129        glsl_type_compare_no_precision(a->interface_type, b->interface_type));
130 
131    /* Types must match. */
132    if (!interface_type_match) {
133       /* Exception: if both the interface blocks are implicitly declared,
134        * don't force their types to match.  They might mismatch due to the two
135        * shaders using different GLSL versions, and that's ok.
136        */
137       if ((a->data.how_declared != nir_var_declared_implicitly ||
138            b->data.how_declared != nir_var_declared_implicitly) &&
139           (!prog->IsES ||
140            interstage_member_mismatch(prog, a->interface_type,
141                                       b->interface_type)))
142          return false;
143    }
144 
145    /* Presence/absence of interface names must match. */
146    if (is_interface_instance(a) != is_interface_instance(b))
147       return false;
148 
149    /* For uniforms, instance names need not match.  For shader ins/outs,
150     * it's not clear from the spec whether they need to match, but
151     * Mesa's implementation relies on them matching.
152     */
153    if (is_interface_instance(a) && b->data.mode != nir_var_mem_ubo &&
154        b->data.mode != nir_var_mem_ssbo &&
155        strcmp(a->name, b->name) != 0) {
156       return false;
157    }
158 
159    bool type_match = (match_precision ?
160                       a->type == b->type :
161                       glsl_type_compare_no_precision(a->type, b->type));
162 
163    /* If a block is an array then it must match across the shader.
164     * Unsized arrays are also processed and matched agaist sized arrays.
165     */
166    if (!type_match && (glsl_type_is_array(b->type) || glsl_type_is_array(a->type)) &&
167        (is_interface_instance(b) || is_interface_instance(a)) &&
168        !gl_nir_validate_intrastage_arrays(prog, b, a, a_stage, match_precision))
169       return false;
170 
171    return true;
172 }
173 
174 /**
175  * Check if two interfaces match, according to interstage (in/out) interface
176  * matching rules.
177  *
178  * If \c extra_array_level is true, the consumer interface is required to be
179  * an array and the producer interface is required to be a non-array.
180  * This is used for tessellation control and geometry shader consumers.
181  */
182 static bool
interstage_match(struct gl_shader_program * prog,nir_variable * producer,nir_variable * consumer,bool extra_array_level)183 interstage_match(struct gl_shader_program *prog, nir_variable *producer,
184                  nir_variable *consumer, bool extra_array_level)
185 {
186    /* Types must match. */
187    if (consumer->interface_type != producer->interface_type) {
188       /* Exception: if both the interface blocks are implicitly declared,
189        * don't force their types to match.  They might mismatch due to the two
190        * shaders using different GLSL versions, and that's ok.
191        *
192        * Also we store some member information such as interpolation in
193        * glsl_type that doesn't always have to match across shader stages.
194        * Therefore we make a pass over the members glsl_struct_field to make
195        * sure we don't reject shaders where fields don't need to match.
196        */
197       if ((consumer->data.how_declared != nir_var_declared_implicitly ||
198            producer->data.how_declared != nir_var_declared_implicitly) &&
199           interstage_member_mismatch(prog, consumer->interface_type,
200                                      producer->interface_type))
201          return false;
202    }
203 
204    /* Ignore outermost array if geom shader */
205    const glsl_type *consumer_instance_type;
206    if (extra_array_level) {
207       consumer_instance_type = glsl_get_array_element(consumer->type);
208    } else {
209       consumer_instance_type = consumer->type;
210    }
211 
212    /* If a block is an array then it must match across shaders.
213     * Since unsized arrays have been ruled out, we can check this by just
214     * making sure the types are equal.
215     */
216    if ((is_interface_instance(consumer) &&
217         glsl_type_is_array(consumer_instance_type)) ||
218        (is_interface_instance(producer) &&
219         glsl_type_is_array(producer->type))) {
220       if (consumer_instance_type != producer->type)
221          return false;
222    }
223 
224    return true;
225 }
226 
227 struct ifc_var {
228    unsigned stage;
229    nir_variable *var;
230 };
231 
232 /**
233  * Lookup the interface definition. Return NULL if none is found.
234  */
235 static struct ifc_var *
ifc_lookup(struct hash_table * ht,nir_variable * var)236 ifc_lookup(struct hash_table *ht, nir_variable *var)
237 {
238    if (var->data.explicit_location &&
239        var->data.location >= VARYING_SLOT_VAR0) {
240       char location_str[11];
241       snprintf(location_str, 11, "%d", var->data.location);
242 
243       const struct hash_entry *entry =
244          _mesa_hash_table_search(ht, location_str);
245       return entry ? (struct ifc_var *) entry->data : NULL;
246    } else {
247       const struct hash_entry *entry =
248          _mesa_hash_table_search(ht,
249             glsl_get_type_name(glsl_without_array(var->interface_type)));
250       return entry ? (struct ifc_var *) entry->data : NULL;
251    }
252 }
253 
254 /**
255  * Add a new interface definition.
256  */
257 static void
ifc_store(void * mem_ctx,struct hash_table * ht,nir_variable * var,unsigned stage)258 ifc_store(void *mem_ctx, struct hash_table *ht, nir_variable *var,
259           unsigned stage)
260 {
261    struct ifc_var *ifc_var = ralloc(mem_ctx, struct ifc_var);
262    ifc_var->var = var;
263    ifc_var->stage = stage;
264 
265    if (var->data.explicit_location &&
266        var->data.location >= VARYING_SLOT_VAR0) {
267       /* If explicit location is given then lookup the variable by location.
268        * We turn the location into a string and use this as the hash key
269        * rather than the name. Note: We allocate enough space for a 32-bit
270        * unsigned location value which is overkill but future proof.
271        */
272       char location_str[11];
273       snprintf(location_str, 11, "%d", var->data.location);
274       _mesa_hash_table_insert(ht, ralloc_strdup(mem_ctx, location_str), ifc_var);
275    } else {
276       _mesa_hash_table_insert(ht,
277          glsl_get_type_name(glsl_without_array(var->interface_type)), ifc_var);
278    }
279 }
280 
281 static const glsl_type *
get_interface(const struct gl_linked_shader * shader,char * name,nir_variable_mode mode)282 get_interface(const struct gl_linked_shader *shader, char *name,
283               nir_variable_mode mode)
284 {
285    nir_foreach_variable_with_modes(var, shader->Program->nir, mode) {
286       if (var->type == var->interface_type) {
287          const char *ifc_name = glsl_get_type_name(var->interface_type);
288          if (strcmp(name, ifc_name) == 0)
289             return var->interface_type;
290       }
291    }
292 
293    return NULL;
294 }
295 
296 static bool
is_builtin_gl_in_block(nir_variable * var,int consumer_stage)297 is_builtin_gl_in_block(nir_variable *var, int consumer_stage)
298 {
299    return !strcmp(var->name, "gl_in") &&
300           (consumer_stage == MESA_SHADER_TESS_CTRL ||
301            consumer_stage == MESA_SHADER_TESS_EVAL ||
302            consumer_stage == MESA_SHADER_GEOMETRY);
303 }
304 
305 void
gl_nir_validate_interstage_inout_blocks(struct gl_shader_program * prog,const struct gl_linked_shader * producer,const struct gl_linked_shader * consumer)306 gl_nir_validate_interstage_inout_blocks(struct gl_shader_program *prog,
307                                         const struct gl_linked_shader *producer,
308                                         const struct gl_linked_shader *consumer)
309 {
310    void *mem_ctx = ralloc_context(NULL);
311    struct hash_table *ht = _mesa_hash_table_create(mem_ctx, _mesa_hash_string,
312                                                    _mesa_key_string_equal);
313 
314    /* VS -> GS, VS -> TCS, VS -> TES, TES -> GS */
315    const bool extra_array_level = (producer->Stage == MESA_SHADER_VERTEX &&
316                                    consumer->Stage != MESA_SHADER_FRAGMENT) ||
317                                   consumer->Stage == MESA_SHADER_GEOMETRY;
318 
319    /* Check that block re-declarations of gl_PerVertex are compatible
320     * across shaders: From OpenGL Shading Language 4.5, section
321     * "7.1 Built-In Language Variables", page 130 of the PDF:
322     *
323     *    "If multiple shaders using members of a built-in block belonging
324     *     to the same interface are linked together in the same program,
325     *     they must all redeclare the built-in block in the same way, as
326     *     described in section 4.3.9 “Interface Blocks” for interface-block
327     *     matching, or a link-time error will result."
328     *
329     * This is done explicitly outside of iterating the member variable
330     * declarations because it is possible that the variables are not used and
331     * so they would have been optimised out.
332     */
333    const glsl_type *consumer_iface =
334       get_interface(consumer, "gl_PerVertex", nir_var_shader_in);
335 
336    const glsl_type *producer_iface =
337       get_interface(producer, "gl_PerVertex", nir_var_shader_out);
338 
339    if (producer_iface && consumer_iface &&
340        interstage_member_mismatch(prog, consumer_iface, producer_iface)) {
341       linker_error(prog, "Incompatible or missing gl_PerVertex re-declaration "
342                    "in consecutive shaders");
343       ralloc_free(mem_ctx);
344       return;
345    }
346 
347    /* Desktop OpenGL requires redeclaration of the built-in interfaces for
348     * SSO programs. Passes above implement following rules:
349     *
350     * From Section 7.4 (Program Pipeline Objects) of the OpenGL 4.6 Core
351     * spec:
352     *
353     *    "To use any built-in input or output in the gl_PerVertex and
354     *     gl_PerFragment blocks in separable program objects, shader code
355     *     must redeclare those blocks prior to use.  A separable program
356     *     will fail to link if:
357     *
358     *     it contains multiple shaders of a single type with different
359     *     redeclarations of these built-in input and output blocks; or
360     *
361     *     any shader uses a built-in block member not found in the
362     *     redeclaration of that block."
363     *
364     * ARB_separate_shader_objects issues section (issue #28) states that
365     * redeclaration is not required for GLSL shaders using #version 140 or
366     * earlier (since interface blocks are not possible with older versions).
367     *
368     * From Section 7.4.1 (Shader Interface Matching) of the OpenGL ES 3.1
369     * spec:
370     *
371     *    "Built-in inputs or outputs do not affect interface matching."
372     *
373     * GL_OES_shader_io_blocks adds following:
374     *
375     *    "When using any built-in input or output in the gl_PerVertex block
376     *     in separable program objects, shader code may redeclare that block
377     *     prior to use. If the shader does not redeclare the block, the
378     *     intrinsically declared definition of that block will be used."
379     */
380 
381    /* Add output interfaces from the producer to the symbol table. */
382    nir_foreach_shader_out_variable(var, producer->Program->nir) {
383       if (!var->interface_type)
384          continue;
385 
386       /* Built-in interface redeclaration check. */
387       if (prog->SeparateShader && !prog->IsES && prog->GLSL_Version >= 150 &&
388           var->data.how_declared == nir_var_declared_implicitly &&
389           var->data.used && !producer_iface) {
390          linker_error(prog, "missing output builtin block %s redeclaration "
391                       "in separable shader program",
392                       glsl_get_type_name(var->interface_type));
393          ralloc_free(mem_ctx);
394          return;
395       }
396 
397       ifc_store(mem_ctx, ht, var, producer->Program->nir->info.stage);
398    }
399 
400    /* Verify that the consumer's input interfaces match. */
401    nir_foreach_shader_in_variable(var, consumer->Program->nir) {
402       if (!var->interface_type)
403          continue;
404 
405       struct ifc_var *ifc_var = ifc_lookup(ht, var);
406       nir_variable *producer_def = ifc_var ? ifc_var->var : NULL;
407 
408       /* Built-in interface redeclaration check. */
409       if (prog->SeparateShader && !prog->IsES && prog->GLSL_Version >= 150 &&
410           var->data.how_declared == nir_var_declared_implicitly &&
411           var->data.used && !producer_iface) {
412          linker_error(prog, "missing input builtin block %s redeclaration "
413                       "in separable shader program",
414                       glsl_get_type_name(var->interface_type));
415          ralloc_free(mem_ctx);
416          return;
417       }
418 
419       /* The producer doesn't generate this input: fail to link. Skip built-in
420        * 'gl_in[]' since that may not be present if the producer does not
421        * write to any of the pre-defined outputs (e.g. if the vertex shader
422        * does not write to gl_Position, etc), which is allowed and results in
423        * undefined behavior.
424        *
425        * From Section 4.3.4 (Inputs) of the GLSL 1.50 spec:
426        *
427        *    "Only the input variables that are actually read need to be written
428        *     by the previous stage; it is allowed to have superfluous
429        *     declarations of input variables."
430        */
431       if (producer_def == NULL &&
432           !is_builtin_gl_in_block(var, consumer->Stage) && var->data.used) {
433          linker_error(prog, "Input block `%s' is not an output of "
434                       "the previous stage\n", glsl_get_type_name(var->interface_type));
435          ralloc_free(mem_ctx);
436          return;
437       }
438 
439       if (producer_def &&
440           !interstage_match(prog, producer_def, var, extra_array_level)) {
441          linker_error(prog, "definitions of interface block `%s' do not "
442                       "match\n", glsl_get_type_name(var->interface_type));
443          ralloc_free(mem_ctx);
444          return;
445       }
446    }
447 
448    ralloc_free(mem_ctx);
449 }
450 
451 void
gl_nir_validate_interstage_uniform_blocks(struct gl_shader_program * prog,struct gl_linked_shader ** stages)452 gl_nir_validate_interstage_uniform_blocks(struct gl_shader_program *prog,
453                                           struct gl_linked_shader **stages)
454 {
455    void *mem_ctx = ralloc_context(NULL);
456 
457    /* Hash table mapping interface block name to a nir_variable */
458    struct hash_table *ht = _mesa_hash_table_create(mem_ctx, _mesa_hash_string,
459                                                    _mesa_key_string_equal);
460 
461    for (int i = 0; i < MESA_SHADER_STAGES; i++) {
462       if (stages[i] == NULL)
463          continue;
464 
465       const struct gl_linked_shader *stage = stages[i];
466       nir_foreach_variable_in_shader(var, stage->Program->nir) {
467          if (!var->interface_type ||
468              (var->data.mode != nir_var_mem_ubo &&
469               var->data.mode != nir_var_mem_ssbo))
470             continue;
471 
472          struct ifc_var *ifc_var = ifc_lookup(ht, var);
473          if (ifc_var == NULL) {
474             ifc_store(mem_ctx, ht, var, i);
475          } else {
476             /* Interstage uniform matching rules are the same as intrastage
477              * uniform matchin rules (for uniforms, it is as though all
478              * shaders are in the same shader stage).
479              */
480             nir_variable *old_def = ifc_var->var;
481             if (!intrastage_match(old_def, var, prog, ifc_var->stage, false)) {
482                linker_error(prog, "definitions of uniform block `%s' do not "
483                             "match\n", glsl_get_type_name(var->interface_type));
484                ralloc_free(mem_ctx);
485                return;
486             }
487          }
488       }
489    }
490 
491    ralloc_free(mem_ctx);
492 }
493