101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2018 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "nir.h"
257ec681f3Smrg#include "gl_nir.h"
2601e04c3fSmrg#include "gl_nir_linker.h"
2701e04c3fSmrg#include "linker_util.h"
2801e04c3fSmrg#include "main/mtypes.h"
297ec681f3Smrg#include "main/shaderobj.h"
3001e04c3fSmrg#include "ir_uniform.h" /* for gl_uniform_storage */
3101e04c3fSmrg
327ec681f3Smrg/**
337ec681f3Smrg * This file included general link methods, using NIR, instead of IR as
3401e04c3fSmrg * the counter-part glsl/linker.cpp
3501e04c3fSmrg */
3601e04c3fSmrg
377ec681f3Smrgstatic bool
387ec681f3Smrgcan_remove_uniform(nir_variable *var, UNUSED void *data)
397ec681f3Smrg{
407ec681f3Smrg   /* Section 2.11.6 (Uniform Variables) of the OpenGL ES 3.0.3 spec
417ec681f3Smrg    * says:
427ec681f3Smrg    *
437ec681f3Smrg    *     "All members of a named uniform block declared with a shared or
447ec681f3Smrg    *     std140 layout qualifier are considered active, even if they are not
457ec681f3Smrg    *     referenced in any shader in the program. The uniform block itself is
467ec681f3Smrg    *     also considered active, even if no member of the block is
477ec681f3Smrg    *     referenced."
487ec681f3Smrg    *
497ec681f3Smrg    * Although the spec doesn't state it std430 layouts are expect to behave
507ec681f3Smrg    * the same way. If the variable is in a uniform block with one of those
517ec681f3Smrg    * layouts, do not eliminate it.
527ec681f3Smrg    */
537ec681f3Smrg   if (nir_variable_is_in_block(var) &&
547ec681f3Smrg       (glsl_get_ifc_packing(var->interface_type) !=
557ec681f3Smrg        GLSL_INTERFACE_PACKING_PACKED))
567ec681f3Smrg      return false;
577ec681f3Smrg
587ec681f3Smrg   if (glsl_get_base_type(glsl_without_array(var->type)) ==
597ec681f3Smrg       GLSL_TYPE_SUBROUTINE)
607ec681f3Smrg      return false;
617ec681f3Smrg
627ec681f3Smrg   /* Uniform initializers could get used by another stage */
637ec681f3Smrg   if (var->constant_initializer)
647ec681f3Smrg      return false;
657ec681f3Smrg
667ec681f3Smrg   return true;
677ec681f3Smrg}
687ec681f3Smrg
697ec681f3Smrg/**
707ec681f3Smrg * Built-in / reserved GL variables names start with "gl_"
717ec681f3Smrg */
727ec681f3Smrgstatic inline bool
737ec681f3Smrgis_gl_identifier(const char *s)
747ec681f3Smrg{
757ec681f3Smrg   return s && s[0] == 'g' && s[1] == 'l' && s[2] == '_';
767ec681f3Smrg}
777ec681f3Smrg
787ec681f3Smrgstatic bool
797ec681f3Smrginout_has_same_location(const nir_variable *var, unsigned stage)
807ec681f3Smrg{
817ec681f3Smrg   if (!var->data.patch &&
827ec681f3Smrg       ((var->data.mode == nir_var_shader_out &&
837ec681f3Smrg         stage == MESA_SHADER_TESS_CTRL) ||
847ec681f3Smrg        (var->data.mode == nir_var_shader_in &&
857ec681f3Smrg         (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL ||
867ec681f3Smrg          stage == MESA_SHADER_GEOMETRY))))
877ec681f3Smrg      return true;
887ec681f3Smrg   else
897ec681f3Smrg      return false;
907ec681f3Smrg}
917ec681f3Smrg
927ec681f3Smrg/**
937ec681f3Smrg * Create gl_shader_variable from nir_variable.
947ec681f3Smrg */
957ec681f3Smrgstatic struct gl_shader_variable *
967ec681f3Smrgcreate_shader_variable(struct gl_shader_program *shProg,
977ec681f3Smrg                       const nir_variable *in,
987ec681f3Smrg                       const char *name, const struct glsl_type *type,
997ec681f3Smrg                       const struct glsl_type *interface_type,
1007ec681f3Smrg                       bool use_implicit_location, int location,
1017ec681f3Smrg                       const struct glsl_type *outermost_struct_type)
1027ec681f3Smrg{
1037ec681f3Smrg   /* Allocate zero-initialized memory to ensure that bitfield padding
1047ec681f3Smrg    * is zero.
1057ec681f3Smrg    */
1067ec681f3Smrg   struct gl_shader_variable *out = rzalloc(shProg,
1077ec681f3Smrg                                            struct gl_shader_variable);
1087ec681f3Smrg   if (!out)
1097ec681f3Smrg      return NULL;
1107ec681f3Smrg
1117ec681f3Smrg   /* Since gl_VertexID may be lowered to gl_VertexIDMESA, but applications
1127ec681f3Smrg    * expect to see gl_VertexID in the program resource list.  Pretend.
1137ec681f3Smrg    */
1147ec681f3Smrg   if (in->data.mode == nir_var_system_value &&
1157ec681f3Smrg       in->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
1167ec681f3Smrg      out->name = ralloc_strdup(shProg, "gl_VertexID");
1177ec681f3Smrg   } else if ((in->data.mode == nir_var_shader_out &&
1187ec681f3Smrg               in->data.location == VARYING_SLOT_TESS_LEVEL_OUTER) ||
1197ec681f3Smrg              (in->data.mode == nir_var_system_value &&
1207ec681f3Smrg               in->data.location == SYSTEM_VALUE_TESS_LEVEL_OUTER)) {
1217ec681f3Smrg      out->name = ralloc_strdup(shProg, "gl_TessLevelOuter");
1227ec681f3Smrg      type = glsl_array_type(glsl_float_type(), 4, 0);
1237ec681f3Smrg   } else if ((in->data.mode == nir_var_shader_out &&
1247ec681f3Smrg               in->data.location == VARYING_SLOT_TESS_LEVEL_INNER) ||
1257ec681f3Smrg              (in->data.mode == nir_var_system_value &&
1267ec681f3Smrg               in->data.location == SYSTEM_VALUE_TESS_LEVEL_INNER)) {
1277ec681f3Smrg      out->name = ralloc_strdup(shProg, "gl_TessLevelInner");
1287ec681f3Smrg      type = glsl_array_type(glsl_float_type(), 2, 0);
1297ec681f3Smrg   } else {
1307ec681f3Smrg      out->name = ralloc_strdup(shProg, name);
1317ec681f3Smrg   }
1327ec681f3Smrg
1337ec681f3Smrg   if (!out->name)
1347ec681f3Smrg      return NULL;
1357ec681f3Smrg
1367ec681f3Smrg   /* The ARB_program_interface_query spec says:
1377ec681f3Smrg    *
1387ec681f3Smrg    *     "Not all active variables are assigned valid locations; the
1397ec681f3Smrg    *     following variables will have an effective location of -1:
1407ec681f3Smrg    *
1417ec681f3Smrg    *      * uniforms declared as atomic counters;
1427ec681f3Smrg    *
1437ec681f3Smrg    *      * members of a uniform block;
1447ec681f3Smrg    *
1457ec681f3Smrg    *      * built-in inputs, outputs, and uniforms (starting with "gl_"); and
1467ec681f3Smrg    *
1477ec681f3Smrg    *      * inputs or outputs not declared with a "location" layout
1487ec681f3Smrg    *        qualifier, except for vertex shader inputs and fragment shader
1497ec681f3Smrg    *        outputs."
1507ec681f3Smrg    */
1517ec681f3Smrg   if (glsl_get_base_type(in->type) == GLSL_TYPE_ATOMIC_UINT ||
1527ec681f3Smrg       is_gl_identifier(in->name) ||
1537ec681f3Smrg       !(in->data.explicit_location || use_implicit_location)) {
1547ec681f3Smrg      out->location = -1;
1557ec681f3Smrg   } else {
1567ec681f3Smrg      out->location = location;
1577ec681f3Smrg   }
1587ec681f3Smrg
1597ec681f3Smrg   out->type = type;
1607ec681f3Smrg   out->outermost_struct_type = outermost_struct_type;
1617ec681f3Smrg   out->interface_type = interface_type;
1627ec681f3Smrg   out->component = in->data.location_frac;
1637ec681f3Smrg   out->index = in->data.index;
1647ec681f3Smrg   out->patch = in->data.patch;
1657ec681f3Smrg   out->mode = in->data.mode;
1667ec681f3Smrg   out->interpolation = in->data.interpolation;
1677ec681f3Smrg   out->precision = in->data.precision;
1687ec681f3Smrg   out->explicit_location = in->data.explicit_location;
1697ec681f3Smrg
1707ec681f3Smrg   return out;
1717ec681f3Smrg}
1727ec681f3Smrg
1737ec681f3Smrgstatic bool
1747ec681f3Smrgadd_shader_variable(const struct gl_context *ctx,
1757ec681f3Smrg                    struct gl_shader_program *shProg,
1767ec681f3Smrg                    struct set *resource_set,
1777ec681f3Smrg                    unsigned stage_mask,
1787ec681f3Smrg                    GLenum programInterface, nir_variable *var,
1797ec681f3Smrg                    const char *name, const struct glsl_type *type,
1807ec681f3Smrg                    bool use_implicit_location, int location,
1817ec681f3Smrg                    bool inouts_share_location,
1827ec681f3Smrg                    const struct glsl_type *outermost_struct_type)
1837ec681f3Smrg{
1847ec681f3Smrg   const struct glsl_type *interface_type = var->interface_type;
1857ec681f3Smrg
1867ec681f3Smrg   if (outermost_struct_type == NULL) {
1877ec681f3Smrg      if (var->data.from_named_ifc_block) {
1887ec681f3Smrg         const char *interface_name = glsl_get_type_name(interface_type);
1897ec681f3Smrg
1907ec681f3Smrg         if (glsl_type_is_array(interface_type)) {
1917ec681f3Smrg            /* Issue #16 of the ARB_program_interface_query spec says:
1927ec681f3Smrg             *
1937ec681f3Smrg             * "* If a variable is a member of an interface block without an
1947ec681f3Smrg             *    instance name, it is enumerated using just the variable name.
1957ec681f3Smrg             *
1967ec681f3Smrg             *  * If a variable is a member of an interface block with an
1977ec681f3Smrg             *    instance name, it is enumerated as "BlockName.Member", where
1987ec681f3Smrg             *    "BlockName" is the name of the interface block (not the
1997ec681f3Smrg             *    instance name) and "Member" is the name of the variable."
2007ec681f3Smrg             *
2017ec681f3Smrg             * In particular, it indicates that it should be "BlockName",
2027ec681f3Smrg             * not "BlockName[array length]".  The conformance suite and
2037ec681f3Smrg             * dEQP both require this behavior.
2047ec681f3Smrg             *
2057ec681f3Smrg             * Here, we unwrap the extra array level added by named interface
2067ec681f3Smrg             * block array lowering so we have the correct variable type.  We
2077ec681f3Smrg             * also unwrap the interface type when constructing the name.
2087ec681f3Smrg             *
2097ec681f3Smrg             * We leave interface_type the same so that ES 3.x SSO pipeline
2107ec681f3Smrg             * validation can enforce the rules requiring array length to
2117ec681f3Smrg             * match on interface blocks.
2127ec681f3Smrg             */
2137ec681f3Smrg            type = glsl_get_array_element(type);
2147ec681f3Smrg
2157ec681f3Smrg            interface_name =
2167ec681f3Smrg               glsl_get_type_name(glsl_get_array_element(interface_type));
2177ec681f3Smrg         }
2187ec681f3Smrg
2197ec681f3Smrg         name = ralloc_asprintf(shProg, "%s.%s", interface_name, name);
2207ec681f3Smrg      }
2217ec681f3Smrg   }
2227ec681f3Smrg
2237ec681f3Smrg   switch (glsl_get_base_type(type)) {
2247ec681f3Smrg   case GLSL_TYPE_STRUCT: {
2257ec681f3Smrg      /* The ARB_program_interface_query spec says:
2267ec681f3Smrg       *
2277ec681f3Smrg       *     "For an active variable declared as a structure, a separate entry
2287ec681f3Smrg       *     will be generated for each active structure member.  The name of
2297ec681f3Smrg       *     each entry is formed by concatenating the name of the structure,
2307ec681f3Smrg       *     the "."  character, and the name of the structure member.  If a
2317ec681f3Smrg       *     structure member to enumerate is itself a structure or array,
2327ec681f3Smrg       *     these enumeration rules are applied recursively."
2337ec681f3Smrg       */
2347ec681f3Smrg      if (outermost_struct_type == NULL)
2357ec681f3Smrg         outermost_struct_type = type;
2367ec681f3Smrg
2377ec681f3Smrg      unsigned field_location = location;
2387ec681f3Smrg      for (unsigned i = 0; i < glsl_get_length(type); i++) {
2397ec681f3Smrg         const struct glsl_type *field_type = glsl_get_struct_field(type, i);
2407ec681f3Smrg         const struct glsl_struct_field *field =
2417ec681f3Smrg            glsl_get_struct_field_data(type, i);
2427ec681f3Smrg
2437ec681f3Smrg         char *field_name = ralloc_asprintf(shProg, "%s.%s", name, field->name);
2447ec681f3Smrg         if (!add_shader_variable(ctx, shProg, resource_set,
2457ec681f3Smrg                                  stage_mask, programInterface,
2467ec681f3Smrg                                  var, field_name, field_type,
2477ec681f3Smrg                                  use_implicit_location, field_location,
2487ec681f3Smrg                                  false, outermost_struct_type))
2497ec681f3Smrg            return false;
2507ec681f3Smrg
2517ec681f3Smrg         field_location += glsl_count_attribute_slots(field_type, false);
2527ec681f3Smrg      }
2537ec681f3Smrg      return true;
2547ec681f3Smrg   }
2557ec681f3Smrg
2567ec681f3Smrg   case GLSL_TYPE_ARRAY: {
2577ec681f3Smrg      /* The ARB_program_interface_query spec says:
2587ec681f3Smrg       *
2597ec681f3Smrg       *     "For an active variable declared as an array of basic types, a
2607ec681f3Smrg       *      single entry will be generated, with its name string formed by
2617ec681f3Smrg       *      concatenating the name of the array and the string "[0]"."
2627ec681f3Smrg       *
2637ec681f3Smrg       *     "For an active variable declared as an array of an aggregate data
2647ec681f3Smrg       *      type (structures or arrays), a separate entry will be generated
2657ec681f3Smrg       *      for each active array element, unless noted immediately below.
2667ec681f3Smrg       *      The name of each entry is formed by concatenating the name of
2677ec681f3Smrg       *      the array, the "[" character, an integer identifying the element
2687ec681f3Smrg       *      number, and the "]" character.  These enumeration rules are
2697ec681f3Smrg       *      applied recursively, treating each enumerated array element as a
2707ec681f3Smrg       *      separate active variable."
2717ec681f3Smrg       */
2727ec681f3Smrg      const struct glsl_type *array_type = glsl_get_array_element(type);
2737ec681f3Smrg      if (glsl_get_base_type(array_type) == GLSL_TYPE_STRUCT ||
2747ec681f3Smrg          glsl_get_base_type(array_type) == GLSL_TYPE_ARRAY) {
2757ec681f3Smrg         unsigned elem_location = location;
2767ec681f3Smrg         unsigned stride = inouts_share_location ? 0 :
2777ec681f3Smrg                           glsl_count_attribute_slots(array_type, false);
2787ec681f3Smrg         for (unsigned i = 0; i < glsl_get_length(type); i++) {
2797ec681f3Smrg            char *elem = ralloc_asprintf(shProg, "%s[%d]", name, i);
2807ec681f3Smrg            if (!add_shader_variable(ctx, shProg, resource_set,
2817ec681f3Smrg                                     stage_mask, programInterface,
2827ec681f3Smrg                                     var, elem, array_type,
2837ec681f3Smrg                                     use_implicit_location, elem_location,
2847ec681f3Smrg                                     false, outermost_struct_type))
2857ec681f3Smrg               return false;
2867ec681f3Smrg            elem_location += stride;
2877ec681f3Smrg         }
2887ec681f3Smrg         return true;
2897ec681f3Smrg      }
2907ec681f3Smrg   }
2917ec681f3Smrg   FALLTHROUGH;
2927ec681f3Smrg
2937ec681f3Smrg   default: {
2947ec681f3Smrg      /* The ARB_program_interface_query spec says:
2957ec681f3Smrg       *
2967ec681f3Smrg       *     "For an active variable declared as a single instance of a basic
2977ec681f3Smrg       *     type, a single entry will be generated, using the variable name
2987ec681f3Smrg       *     from the shader source."
2997ec681f3Smrg       */
3007ec681f3Smrg      struct gl_shader_variable *sha_v =
3017ec681f3Smrg         create_shader_variable(shProg, var, name, type, interface_type,
3027ec681f3Smrg                                use_implicit_location, location,
3037ec681f3Smrg                                outermost_struct_type);
3047ec681f3Smrg      if (!sha_v)
3057ec681f3Smrg         return false;
3067ec681f3Smrg
3077ec681f3Smrg      return link_util_add_program_resource(shProg, resource_set,
3087ec681f3Smrg                                            programInterface, sha_v, stage_mask);
3097ec681f3Smrg   }
3107ec681f3Smrg   }
3117ec681f3Smrg}
3127ec681f3Smrg
3137ec681f3Smrgstatic bool
3147ec681f3Smrgadd_vars_with_modes(const struct gl_context *ctx,
3157ec681f3Smrg                    struct gl_shader_program *prog, struct set *resource_set,
3167ec681f3Smrg                    nir_shader *nir, nir_variable_mode modes,
3177ec681f3Smrg                    unsigned stage, GLenum programInterface)
3187ec681f3Smrg{
3197ec681f3Smrg   nir_foreach_variable_with_modes(var, nir, modes) {
3207ec681f3Smrg      if (var->data.how_declared == nir_var_hidden)
3217ec681f3Smrg         continue;
3227ec681f3Smrg
3237ec681f3Smrg      int loc_bias = 0;
3247ec681f3Smrg      switch(var->data.mode) {
3257ec681f3Smrg      case nir_var_system_value:
3267ec681f3Smrg      case nir_var_shader_in:
3277ec681f3Smrg         if (programInterface != GL_PROGRAM_INPUT)
3287ec681f3Smrg            continue;
3297ec681f3Smrg         loc_bias = (stage == MESA_SHADER_VERTEX) ? VERT_ATTRIB_GENERIC0
3307ec681f3Smrg                                                  : VARYING_SLOT_VAR0;
3317ec681f3Smrg         break;
3327ec681f3Smrg      case nir_var_shader_out:
3337ec681f3Smrg         if (programInterface != GL_PROGRAM_OUTPUT)
3347ec681f3Smrg            continue;
3357ec681f3Smrg         loc_bias = (stage == MESA_SHADER_FRAGMENT) ? FRAG_RESULT_DATA0
3367ec681f3Smrg                                                    : VARYING_SLOT_VAR0;
3377ec681f3Smrg         break;
3387ec681f3Smrg      default:
3397ec681f3Smrg         continue;
3407ec681f3Smrg      }
3417ec681f3Smrg
3427ec681f3Smrg      if (var->data.patch)
3437ec681f3Smrg         loc_bias = VARYING_SLOT_PATCH0;
3447ec681f3Smrg
3457ec681f3Smrg      if (prog->data->spirv) {
3467ec681f3Smrg         struct gl_shader_variable *sh_var =
3477ec681f3Smrg            rzalloc(prog, struct gl_shader_variable);
3487ec681f3Smrg
3497ec681f3Smrg         /* In the ARB_gl_spirv spec, names are considered optional debug info, so
3507ec681f3Smrg          * the linker needs to work without them. Returning them is optional.
3517ec681f3Smrg          * For simplicity, we ignore names.
3527ec681f3Smrg          */
3537ec681f3Smrg         sh_var->name = NULL;
3547ec681f3Smrg         sh_var->type = var->type;
3557ec681f3Smrg         sh_var->location = var->data.location - loc_bias;
3567ec681f3Smrg         sh_var->index = var->data.index;
3577ec681f3Smrg
3587ec681f3Smrg         if (!link_util_add_program_resource(prog, resource_set,
3597ec681f3Smrg                                             programInterface,
3607ec681f3Smrg                                             sh_var, 1 << stage)) {
3617ec681f3Smrg           return false;
3627ec681f3Smrg         }
3637ec681f3Smrg      } else {
3647ec681f3Smrg         /* Skip packed varyings, packed varyings are handled separately
3657ec681f3Smrg          * by add_packed_varyings in the GLSL IR
3667ec681f3Smrg          * build_program_resource_list() call.
3677ec681f3Smrg          * TODO: handle packed varyings here instead. We likely want a NIR
3687ec681f3Smrg          * based packing pass first.
3697ec681f3Smrg          */
3707ec681f3Smrg         if (strncmp(var->name, "packed:", 7) == 0)
3717ec681f3Smrg            continue;
3727ec681f3Smrg
3737ec681f3Smrg         const bool vs_input_or_fs_output =
3747ec681f3Smrg            (stage == MESA_SHADER_VERTEX &&
3757ec681f3Smrg             var->data.mode == nir_var_shader_in) ||
3767ec681f3Smrg            (stage == MESA_SHADER_FRAGMENT &&
3777ec681f3Smrg             var->data.mode == nir_var_shader_out);
3787ec681f3Smrg
3797ec681f3Smrg         if (!add_shader_variable(ctx, prog, resource_set,
3807ec681f3Smrg                                  1 << stage, programInterface,
3817ec681f3Smrg                                  var, var->name, var->type,
3827ec681f3Smrg                                  vs_input_or_fs_output,
3837ec681f3Smrg                                  var->data.location - loc_bias,
3847ec681f3Smrg                                  inout_has_same_location(var, stage),
3857ec681f3Smrg                                  NULL))
3867ec681f3Smrg            return false;
3877ec681f3Smrg      }
3887ec681f3Smrg   }
3897ec681f3Smrg
3907ec681f3Smrg   return true;
3917ec681f3Smrg}
3927ec681f3Smrg
3937ec681f3Smrgstatic bool
3947ec681f3Smrgadd_interface_variables(const struct gl_context *ctx,
3957ec681f3Smrg                        struct gl_shader_program *prog,
3967ec681f3Smrg                        struct set *resource_set,
3977ec681f3Smrg                        unsigned stage, GLenum programInterface)
3987ec681f3Smrg{
3997ec681f3Smrg   struct gl_linked_shader *sh = prog->_LinkedShaders[stage];
4007ec681f3Smrg   if (!sh)
4017ec681f3Smrg      return true;
4027ec681f3Smrg
4037ec681f3Smrg   nir_shader *nir = sh->Program->nir;
4047ec681f3Smrg   assert(nir);
4057ec681f3Smrg
4067ec681f3Smrg   switch (programInterface) {
4077ec681f3Smrg   case GL_PROGRAM_INPUT: {
4087ec681f3Smrg      return add_vars_with_modes(ctx, prog, resource_set,
4097ec681f3Smrg                                 nir, nir_var_shader_in | nir_var_system_value,
4107ec681f3Smrg                                 stage, programInterface);
4117ec681f3Smrg   }
4127ec681f3Smrg   case GL_PROGRAM_OUTPUT:
4137ec681f3Smrg      return add_vars_with_modes(ctx, prog, resource_set,
4147ec681f3Smrg                                 nir, nir_var_shader_out,
4157ec681f3Smrg                                 stage, programInterface);
4167ec681f3Smrg   default:
4177ec681f3Smrg      assert("!Should not get here");
4187ec681f3Smrg      break;
4197ec681f3Smrg   }
4207ec681f3Smrg
4217ec681f3Smrg   return false;
4227ec681f3Smrg}
4237ec681f3Smrg
4247ec681f3Smrg/* TODO: as we keep adding features, this method is becoming more and more
4257ec681f3Smrg * similar to its GLSL counterpart at linker.cpp. Eventually it would be good
4267ec681f3Smrg * to check if they could be refactored, and reduce code duplication somehow
4277ec681f3Smrg */
42801e04c3fSmrgvoid
42901e04c3fSmrgnir_build_program_resource_list(struct gl_context *ctx,
4307ec681f3Smrg                                struct gl_shader_program *prog,
4317ec681f3Smrg                                bool rebuild_resourse_list)
43201e04c3fSmrg{
43301e04c3fSmrg   /* Rebuild resource list. */
4347ec681f3Smrg   if (prog->data->ProgramResourceList && rebuild_resourse_list) {
43501e04c3fSmrg      ralloc_free(prog->data->ProgramResourceList);
43601e04c3fSmrg      prog->data->ProgramResourceList = NULL;
43701e04c3fSmrg      prog->data->NumProgramResourceList = 0;
43801e04c3fSmrg   }
43901e04c3fSmrg
4407ec681f3Smrg   int input_stage = MESA_SHADER_STAGES, output_stage = 0;
4417ec681f3Smrg
4427ec681f3Smrg   /* Determine first input and final output stage. These are used to
4437ec681f3Smrg    * detect which variables should be enumerated in the resource list
4447ec681f3Smrg    * for GL_PROGRAM_INPUT and GL_PROGRAM_OUTPUT.
4457ec681f3Smrg    */
4467ec681f3Smrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
4477ec681f3Smrg      if (!prog->_LinkedShaders[i])
4487ec681f3Smrg         continue;
4497ec681f3Smrg      if (input_stage == MESA_SHADER_STAGES)
4507ec681f3Smrg         input_stage = i;
4517ec681f3Smrg      output_stage = i;
4527ec681f3Smrg   }
4537ec681f3Smrg
4547ec681f3Smrg   /* Empty shader, no resources. */
4557ec681f3Smrg   if (input_stage == MESA_SHADER_STAGES && output_stage == 0)
4567ec681f3Smrg      return;
4577ec681f3Smrg
4587e102996Smaya   struct set *resource_set = _mesa_pointer_set_create(NULL);
45901e04c3fSmrg
4607ec681f3Smrg   /* Add inputs and outputs to the resource list. */
4617ec681f3Smrg   if (!add_interface_variables(ctx, prog, resource_set, input_stage,
4627ec681f3Smrg                                GL_PROGRAM_INPUT)) {
4637ec681f3Smrg      return;
4647ec681f3Smrg   }
4657ec681f3Smrg
4667ec681f3Smrg   if (!add_interface_variables(ctx, prog, resource_set, output_stage,
4677ec681f3Smrg                                GL_PROGRAM_OUTPUT)) {
4687ec681f3Smrg      return;
4697ec681f3Smrg   }
4707ec681f3Smrg
4717ec681f3Smrg   /* Add transform feedback varyings and buffers. */
4727ec681f3Smrg   if (prog->last_vert_prog) {
4737ec681f3Smrg      struct gl_transform_feedback_info *linked_xfb =
4747ec681f3Smrg         prog->last_vert_prog->sh.LinkedTransformFeedback;
4757ec681f3Smrg
4767ec681f3Smrg      /* Add varyings. */
4777ec681f3Smrg      if (linked_xfb->NumVarying > 0) {
4787ec681f3Smrg         for (int i = 0; i < linked_xfb->NumVarying; i++) {
4797ec681f3Smrg            if (!link_util_add_program_resource(prog, resource_set,
4807ec681f3Smrg                                                GL_TRANSFORM_FEEDBACK_VARYING,
4817ec681f3Smrg                                                &linked_xfb->Varyings[i], 0))
4827ec681f3Smrg            return;
4837ec681f3Smrg         }
4847ec681f3Smrg      }
4857ec681f3Smrg
4867ec681f3Smrg      /* Add buffers. */
4877ec681f3Smrg      for (unsigned i = 0; i < ctx->Const.MaxTransformFeedbackBuffers; i++) {
4887ec681f3Smrg         if ((linked_xfb->ActiveBuffers >> i) & 1) {
4897ec681f3Smrg            linked_xfb->Buffers[i].Binding = i;
4907ec681f3Smrg            if (!link_util_add_program_resource(prog, resource_set,
4917ec681f3Smrg                                                GL_TRANSFORM_FEEDBACK_BUFFER,
4927ec681f3Smrg                                                &linked_xfb->Buffers[i], 0))
4937ec681f3Smrg            return;
4947ec681f3Smrg         }
4957ec681f3Smrg      }
4967ec681f3Smrg   }
4977ec681f3Smrg
49801e04c3fSmrg   /* Add uniforms
49901e04c3fSmrg    *
50001e04c3fSmrg    * Here, it is expected that nir_link_uniforms() has already been
50101e04c3fSmrg    * called, so that UniformStorage table is already available.
50201e04c3fSmrg    */
5037ec681f3Smrg   int top_level_array_base_offset = -1;
5047ec681f3Smrg   int top_level_array_size_in_bytes = -1;
5057ec681f3Smrg   int second_element_offset = -1;
5067ec681f3Smrg   int block_index = -1;
50701e04c3fSmrg   for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
50801e04c3fSmrg      struct gl_uniform_storage *uniform = &prog->data->UniformStorage[i];
50901e04c3fSmrg
5107ec681f3Smrg      if (uniform->hidden) {
5117ec681f3Smrg         for (int j = MESA_SHADER_VERTEX; j < MESA_SHADER_STAGES; j++) {
5127ec681f3Smrg            if (!uniform->opaque[j].active ||
5137ec681f3Smrg                glsl_get_base_type(uniform->type) != GLSL_TYPE_SUBROUTINE)
5147ec681f3Smrg               continue;
5157ec681f3Smrg
5167ec681f3Smrg            GLenum type =
5177ec681f3Smrg               _mesa_shader_stage_to_subroutine_uniform((gl_shader_stage)j);
5187ec681f3Smrg            /* add shader subroutines */
5197ec681f3Smrg            if (!link_util_add_program_resource(prog, resource_set,
5207ec681f3Smrg                                                type, uniform, 0))
5217ec681f3Smrg               return;
5227ec681f3Smrg         }
5237ec681f3Smrg
5247ec681f3Smrg         continue;
5257ec681f3Smrg      }
5267ec681f3Smrg
5277ec681f3Smrg      if (!link_util_should_add_buffer_variable(prog, uniform,
5287ec681f3Smrg                                                top_level_array_base_offset,
5297ec681f3Smrg                                                top_level_array_size_in_bytes,
5307ec681f3Smrg                                                second_element_offset, block_index))
53101e04c3fSmrg         continue;
53201e04c3fSmrg
5337ec681f3Smrg
5347ec681f3Smrg      if (prog->data->UniformStorage[i].offset >= second_element_offset) {
5357ec681f3Smrg         top_level_array_base_offset =
5367ec681f3Smrg            prog->data->UniformStorage[i].offset;
5377ec681f3Smrg
5387ec681f3Smrg         top_level_array_size_in_bytes =
5397ec681f3Smrg            prog->data->UniformStorage[i].top_level_array_size *
5407ec681f3Smrg            prog->data->UniformStorage[i].top_level_array_stride;
5417ec681f3Smrg
5427ec681f3Smrg         /* Set or reset the second element offset. For non arrays this
5437ec681f3Smrg          * will be set to -1.
5447ec681f3Smrg          */
5457ec681f3Smrg         second_element_offset = top_level_array_size_in_bytes ?
5467ec681f3Smrg            top_level_array_base_offset +
5477ec681f3Smrg            prog->data->UniformStorage[i].top_level_array_stride : -1;
5487ec681f3Smrg      }
5497ec681f3Smrg      block_index = uniform->block_index;
5507ec681f3Smrg
5517ec681f3Smrg
5527ec681f3Smrg      GLenum interface = uniform->is_shader_storage ? GL_BUFFER_VARIABLE : GL_UNIFORM;
5537ec681f3Smrg      if (!link_util_add_program_resource(prog, resource_set, interface, uniform,
55401e04c3fSmrg                                          uniform->active_shader_mask)) {
55501e04c3fSmrg         return;
55601e04c3fSmrg      }
55701e04c3fSmrg   }
55801e04c3fSmrg
55901e04c3fSmrg
5607ec681f3Smrg   for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
5617ec681f3Smrg      if (!link_util_add_program_resource(prog, resource_set, GL_UNIFORM_BLOCK,
5627ec681f3Smrg                                          &prog->data->UniformBlocks[i],
5637ec681f3Smrg                                          prog->data->UniformBlocks[i].stageref))
5647ec681f3Smrg         return;
5657ec681f3Smrg   }
5667ec681f3Smrg
5677ec681f3Smrg   for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
5687ec681f3Smrg      if (!link_util_add_program_resource(prog, resource_set, GL_SHADER_STORAGE_BLOCK,
5697ec681f3Smrg                                          &prog->data->ShaderStorageBlocks[i],
5707ec681f3Smrg                                          prog->data->ShaderStorageBlocks[i].stageref))
5717ec681f3Smrg         return;
5727ec681f3Smrg   }
5737ec681f3Smrg
5747ec681f3Smrg   /* Add atomic counter buffers. */
5757ec681f3Smrg   for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
5767ec681f3Smrg      if (!link_util_add_program_resource(prog, resource_set, GL_ATOMIC_COUNTER_BUFFER,
5777ec681f3Smrg                                          &prog->data->AtomicBuffers[i], 0))
5787ec681f3Smrg         return;
5797ec681f3Smrg   }
5807ec681f3Smrg
5817ec681f3Smrg   unsigned mask = prog->data->linked_stages;
5827ec681f3Smrg   while (mask) {
5837ec681f3Smrg      const int i = u_bit_scan(&mask);
5847ec681f3Smrg      struct gl_program *p = prog->_LinkedShaders[i]->Program;
5857ec681f3Smrg
5867ec681f3Smrg      GLuint type = _mesa_shader_stage_to_subroutine((gl_shader_stage)i);
5877ec681f3Smrg      for (unsigned j = 0; j < p->sh.NumSubroutineFunctions; j++) {
5887ec681f3Smrg         if (!link_util_add_program_resource(prog, resource_set,
5897ec681f3Smrg                                             type,
5907ec681f3Smrg                                             &p->sh.SubroutineFunctions[j],
5917ec681f3Smrg                                             0))
5927ec681f3Smrg            return;
5937ec681f3Smrg      }
5947ec681f3Smrg   }
5957ec681f3Smrg
59601e04c3fSmrg   _mesa_set_destroy(resource_set, NULL);
59701e04c3fSmrg}
5987ec681f3Smrg
5997ec681f3Smrgbool
6007ec681f3Smrggl_nir_link_spirv(struct gl_context *ctx, struct gl_shader_program *prog,
6017ec681f3Smrg                  const struct gl_nir_linker_options *options)
6027ec681f3Smrg{
6037ec681f3Smrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
6047ec681f3Smrg      struct gl_linked_shader *shader = prog->_LinkedShaders[i];
6057ec681f3Smrg      if (shader) {
6067ec681f3Smrg         const nir_remove_dead_variables_options opts = {
6077ec681f3Smrg            .can_remove_var = can_remove_uniform,
6087ec681f3Smrg         };
6097ec681f3Smrg         nir_remove_dead_variables(shader->Program->nir, nir_var_uniform,
6107ec681f3Smrg                                   &opts);
6117ec681f3Smrg      }
6127ec681f3Smrg   }
6137ec681f3Smrg
6147ec681f3Smrg   if (!gl_nir_link_uniform_blocks(ctx, prog))
6157ec681f3Smrg      return false;
6167ec681f3Smrg
6177ec681f3Smrg   if (!gl_nir_link_uniforms(ctx, prog, options->fill_parameters))
6187ec681f3Smrg      return false;
6197ec681f3Smrg
6207ec681f3Smrg   gl_nir_link_assign_atomic_counter_resources(ctx, prog);
6217ec681f3Smrg   gl_nir_link_assign_xfb_resources(ctx, prog);
6227ec681f3Smrg
6237ec681f3Smrg   return true;
6247ec681f3Smrg}
6257ec681f3Smrg
6267ec681f3Smrg/**
6277ec681f3Smrg * Validate shader image resources.
6287ec681f3Smrg */
6297ec681f3Smrgstatic void
6307ec681f3Smrgcheck_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
6317ec681f3Smrg{
6327ec681f3Smrg   unsigned total_image_units = 0;
6337ec681f3Smrg   unsigned fragment_outputs = 0;
6347ec681f3Smrg   unsigned total_shader_storage_blocks = 0;
6357ec681f3Smrg
6367ec681f3Smrg   if (!ctx->Extensions.ARB_shader_image_load_store)
6377ec681f3Smrg      return;
6387ec681f3Smrg
6397ec681f3Smrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
6407ec681f3Smrg      struct gl_linked_shader *sh = prog->_LinkedShaders[i];
6417ec681f3Smrg      if (!sh)
6427ec681f3Smrg         continue;
6437ec681f3Smrg
6447ec681f3Smrg      total_image_units += sh->Program->info.num_images;
6457ec681f3Smrg      total_shader_storage_blocks += sh->Program->info.num_ssbos;
6467ec681f3Smrg   }
6477ec681f3Smrg
6487ec681f3Smrg   if (total_image_units > ctx->Const.MaxCombinedImageUniforms)
6497ec681f3Smrg      linker_error(prog, "Too many combined image uniforms\n");
6507ec681f3Smrg
6517ec681f3Smrg   struct gl_linked_shader *frag_sh =
6527ec681f3Smrg      prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
6537ec681f3Smrg   if (frag_sh) {
6547ec681f3Smrg      uint64_t frag_outputs_written = frag_sh->Program->info.outputs_written;
6557ec681f3Smrg      fragment_outputs = util_bitcount64(frag_outputs_written);
6567ec681f3Smrg   }
6577ec681f3Smrg
6587ec681f3Smrg   if (total_image_units + fragment_outputs + total_shader_storage_blocks >
6597ec681f3Smrg       ctx->Const.MaxCombinedShaderOutputResources)
6607ec681f3Smrg      linker_error(prog, "Too many combined image uniforms, shader storage "
6617ec681f3Smrg                         " buffers and fragment outputs\n");
6627ec681f3Smrg}
6637ec681f3Smrg
6647ec681f3Smrgbool
6657ec681f3Smrggl_nir_link_glsl(struct gl_context *ctx, struct gl_shader_program *prog)
6667ec681f3Smrg{
6677ec681f3Smrg   for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
6687ec681f3Smrg      struct gl_linked_shader *shader = prog->_LinkedShaders[i];
6697ec681f3Smrg      if (shader) {
6707ec681f3Smrg         const nir_remove_dead_variables_options opts = {
6717ec681f3Smrg            .can_remove_var = can_remove_uniform,
6727ec681f3Smrg         };
6737ec681f3Smrg         nir_remove_dead_variables(shader->Program->nir, nir_var_uniform,
6747ec681f3Smrg                                   &opts);
6757ec681f3Smrg      }
6767ec681f3Smrg   }
6777ec681f3Smrg
6787ec681f3Smrg   if (!gl_nir_link_uniforms(ctx, prog, true))
6797ec681f3Smrg      return false;
6807ec681f3Smrg
6817ec681f3Smrg   link_util_calculate_subroutine_compat(prog);
6827ec681f3Smrg   link_util_check_uniform_resources(ctx, prog);
6837ec681f3Smrg   link_util_check_subroutine_resources(prog);
6847ec681f3Smrg   check_image_resources(ctx, prog);
6857ec681f3Smrg   gl_nir_link_assign_atomic_counter_resources(ctx, prog);
6867ec681f3Smrg   gl_nir_link_check_atomic_counter_resources(ctx, prog);
6877ec681f3Smrg
6887ec681f3Smrg   if (prog->data->LinkStatus == LINKING_FAILURE)
6897ec681f3Smrg      return false;
6907ec681f3Smrg
6917ec681f3Smrg   return true;
6927ec681f3Smrg}
693