docs: Add sha256 sums for the 10.5.1 release
[mesa.git] / src / glsl / linker.cpp
index 497a77aeab4a4eef05bba3e665200309821e6b6b..0c4467779707fcc7b9fb90cb982ef051a242869f 100644 (file)
@@ -64,6 +64,7 @@
  * \author Ian Romanick <ian.d.romanick@intel.com>
  */
 
+#include <ctype.h>
 #include "main/core.h"
 #include "glsl_symbol_table.h"
 #include "glsl_parser_extras.h"
 #include "ir_rvalue_visitor.h"
 #include "ir_uniform.h"
 
-extern "C" {
 #include "main/shaderobj.h"
 #include "main/enums.h"
-}
+
 
 void linker_error(gl_shader_program *, const char *, ...);
 
@@ -559,14 +559,21 @@ validate_vertex_shader_executable(struct gl_shader_program *prog,
     *      vertex processing has occurred. Its value is undefined if
     *      the vertex shader executable does not write gl_Position."
     *
-    * GLSL ES 3.00 is similar to GLSL 1.40--failing to write to gl_Position is
-    * not an error.
+    * All GLSL ES Versions are similar to GLSL 1.40--failing to write to
+    * gl_Position is not an error.
     */
    if (prog->Version < (prog->IsES ? 300 : 140)) {
       find_assignment_visitor find("gl_Position");
       find.run(shader->ir);
       if (!find.variable_found()) {
-        linker_error(prog, "vertex shader does not write to `gl_Position'\n");
+        if (prog->IsES) {
+          linker_warning(prog,
+                         "vertex shader does not write to `gl_Position'."
+                         "It's value is undefined. \n");
+        } else {
+          linker_error(prog,
+                       "vertex shader does not write to `gl_Position'. \n");
+        }
         return;
       }
    }
@@ -635,7 +642,7 @@ validate_geometry_shader_emissions(struct gl_context *ctx,
       emit_vertex.run(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir);
       if (emit_vertex.error()) {
          linker_error(prog, "Invalid call %s(%d). Accepted values for the "
-                      "stream parameter are in the range [0, %d].",
+                      "stream parameter are in the range [0, %d].\n",
                       emit_vertex.error_func(),
                       emit_vertex.error_stream(),
                       ctx->Const.MaxVertexStreams - 1);
@@ -669,11 +676,50 @@ validate_geometry_shader_emissions(struct gl_context *ctx,
        */
       if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) {
          linker_error(prog, "EmitStreamVertex(n) and EndStreamPrimitive(n) "
-                      "with n>0 requires point output");
+                      "with n>0 requires point output\n");
       }
    }
 }
 
+bool
+validate_intrastage_arrays(struct gl_shader_program *prog,
+                           ir_variable *const var,
+                          ir_variable *const existing)
+{
+   /* Consider the types to be "the same" if both types are arrays
+    * of the same type and one of the arrays is implicitly sized.
+    * In addition, set the type of the linked variable to the
+    * explicitly sized array.
+    */
+   if (var->type->is_array() && existing->type->is_array() &&
+       (var->type->fields.array == existing->type->fields.array) &&
+       ((var->type->length == 0)|| (existing->type->length == 0))) {
+      if (var->type->length != 0) {
+         if (var->type->length <= existing->data.max_array_access) {
+            linker_error(prog, "%s `%s' declared as type "
+                         "`%s' but outermost dimension has an index"
+                         " of `%i'\n",
+                         mode_string(var),
+                         var->name, var->type->name,
+                         existing->data.max_array_access);
+         }
+         existing->type = var->type;
+         return true;
+      } else if (existing->type->length != 0) {
+         if(existing->type->length <= var->data.max_array_access) {
+            linker_error(prog, "%s `%s' declared as type "
+                         "`%s' but outermost dimension has an index"
+                         " of `%i'\n",
+                         mode_string(var),
+                         var->name, existing->type->name,
+                         var->data.max_array_access);
+         }
+         return true;
+      }
+   }
+   return false;
+}
+
 
 /**
  * Perform validation of global variables used across multiple shaders
@@ -713,31 +759,23 @@ cross_validate_globals(struct gl_shader_program *prog,
          */
         ir_variable *const existing = variables.get_variable(var->name);
         if (existing != NULL) {
-           if (var->type != existing->type) {
-              /* Consider the types to be "the same" if both types are arrays
-               * of the same type and one of the arrays is implicitly sized.
-               * In addition, set the type of the linked variable to the
-               * explicitly sized array.
-               */
-              if (var->type->is_array()
-                  && existing->type->is_array()
-                  && (var->type->fields.array == existing->type->fields.array)
-                  && ((var->type->length == 0)
-                      || (existing->type->length == 0))) {
-                 if (var->type->length != 0) {
-                    existing->type = var->type;
-                 }
-               } else if (var->type->is_record()
-                  && existing->type->is_record()
-                  && existing->type->record_compare(var->type)) {
-                 existing->type = var->type;
-              } else {
-                 linker_error(prog, "%s `%s' declared as type "
-                              "`%s' and type `%s'\n",
-                              mode_string(var),
-                              var->name, var->type->name,
-                              existing->type->name);
-                 return;
+            /* Check if types match. Interface blocks have some special
+             * rules so we handle those elsewhere.
+             */
+           if (var->type != existing->type &&
+                !var->is_interface_instance()) {
+              if (!validate_intrastage_arrays(prog, var, existing)) {
+                  if (var->type->is_record() && existing->type->is_record()
+                      && existing->type->record_compare(var->type)) {
+                     existing->type = var->type;
+                  } else {
+                     linker_error(prog, "%s `%s' declared as type "
+                                  "`%s' and type `%s'\n",
+                                  mode_string(var),
+                                  var->name, var->type->name,
+                                  existing->type->name);
+                     return;
+                  }
               }
            }
 
@@ -801,7 +839,7 @@ cross_validate_globals(struct gl_shader_program *prog,
                  linker_error(prog,
                               "All redeclarations of gl_FragDepth in all "
                               "fragment shaders in a single program must have "
-                              "the same set of qualifiers.");
+                              "the same set of qualifiers.\n");
               }
 
               if (var->data.used && layout_differs) {
@@ -810,7 +848,7 @@ cross_validate_globals(struct gl_shader_program *prog,
                               "qualifier in any fragment shader, it must be "
                               "redeclared with the same layout qualifier in "
                               "all fragment shaders that have assignments to "
-                              "gl_FragDepth");
+                              "gl_FragDepth\n");
               }
            }
 
@@ -941,7 +979,7 @@ interstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
                                                       &sh->UniformBlocks[j]);
 
         if (index == -1) {
-           linker_error(prog, "uniform block `%s' has mismatching definitions",
+           linker_error(prog, "uniform block `%s' has mismatching definitions\n",
                         sh->UniformBlocks[j].Name);
            return false;
         }
@@ -969,7 +1007,8 @@ populate_symbol_table(gl_shader *sh)
       if ((func = inst->as_function()) != NULL) {
         sh->symbols->add_function(func);
       } else if ((var = inst->as_variable()) != NULL) {
-        sh->symbols->add_variable(var);
+         if (var->data.mode != ir_var_temporary)
+            sh->symbols->add_variable(var);
       }
    }
 }
@@ -1115,8 +1154,8 @@ move_non_declarations(exec_list *instructions, exec_node *last,
 /**
  * Get the function signature for main from a shader
  */
-static ir_function_signature *
-get_main_function_signature(gl_shader *sh)
+ir_function_signature *
+link_get_main_function_signature(gl_shader *sh)
 {
    ir_function *const f = sh->symbols->get_function("main");
    if (f != NULL) {
@@ -1166,7 +1205,8 @@ public:
       if (var->type->is_interface()) {
          if (interface_contains_unsized_arrays(var->type)) {
             const glsl_type *new_type =
-               resize_interface_members(var->type, var->max_ifc_array_access);
+               resize_interface_members(var->type,
+                                        var->get_max_ifc_array_access());
             var->type = new_type;
             var->change_interface_type(new_type);
          }
@@ -1175,7 +1215,7 @@ public:
          if (interface_contains_unsized_arrays(var->type->fields.array)) {
             const glsl_type *new_type =
                resize_interface_members(var->type->fields.array,
-                                        var->max_ifc_array_access);
+                                        var->get_max_ifc_array_access());
             var->change_interface_type(new_type);
             var->type =
                glsl_type::get_array_instance(new_type, var->type->length);
@@ -1626,7 +1666,7 @@ link_intrastage_shaders(void *mem_ctx,
 
               if ((other_sig != NULL) && other_sig->is_defined
                   && !other_sig->is_builtin()) {
-                 linker_error(prog, "function `%s' is multiply defined",
+                 linker_error(prog, "function `%s' is multiply defined\n",
                               f->name);
                  return NULL;
               }
@@ -1644,7 +1684,7 @@ link_intrastage_shaders(void *mem_ctx,
     */
    gl_shader *main = NULL;
    for (unsigned i = 0; i < num_shaders; i++) {
-      if (get_main_function_signature(shader_list[i]) != NULL) {
+      if (link_get_main_function_signature(shader_list[i]) != NULL) {
         main = shader_list[i];
         break;
       }
@@ -1670,10 +1710,11 @@ link_intrastage_shaders(void *mem_ctx,
 
    populate_symbol_table(linked);
 
-   /* The pointer to the main function in the final linked shader (i.e., the
+   /* The pointer to the main function in the final linked shader (i.e., the
     * copy of the original shader that contained the main function).
     */
-   ir_function_signature *const main_sig = get_main_function_signature(linked);
+   ir_function_signature *const main_sig =
+      link_get_main_function_signature(linked);
 
    /* Move any instructions other than variable declarations or function
     * declarations into main.
@@ -1706,12 +1747,19 @@ link_intrastage_shaders(void *mem_ctx,
        */
       gl_shader **linking_shaders = (gl_shader **)
          calloc(num_shaders + 1, sizeof(gl_shader *));
-      memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
-      linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
 
-      ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
+      ok = linking_shaders != NULL;
+
+      if (ok) {
+         memcpy(linking_shaders, shader_list, num_shaders * sizeof(gl_shader *));
+         linking_shaders[num_shaders] = _mesa_glsl_get_builtin_function_shader();
 
-      free(linking_shaders);
+         ok = link_function_calls(prog, linked, linking_shaders, num_shaders + 1);
+
+         free(linking_shaders);
+      } else {
+         _mesa_error_no_memory(__func__);
+      }
    } else {
       ok = link_function_calls(prog, linked, shader_list, num_shaders);
    }
@@ -1736,6 +1784,9 @@ link_intrastage_shaders(void *mem_ctx,
       }
    }
 
+   if (ctx->Const.VertexID_is_zero_based)
+      lower_vertex_id(linked);
+
    /* Make a pass over all variable declarations to ensure that arrays with
     * unspecified sizes have a size specified.  The size is inferred from the
     * max_array_access field.
@@ -1813,9 +1864,10 @@ update_array_sizes(struct gl_shader_program *prog)
             * Determine the number of slots per array element by dividing by
             * the old (total) size.
             */
-           if (var->num_state_slots > 0) {
-              var->num_state_slots = (size + 1)
-                 * (var->num_state_slots / var->type->length);
+            const unsigned num_slots = var->get_num_state_slots();
+           if (num_slots > 0) {
+              var->set_num_state_slots((size + 1)
+                                        * (num_slots / var->type->length));
            }
 
            var->type = glsl_type::get_array_instance(var->type->fields.array,
@@ -1861,7 +1913,7 @@ find_available_slots(unsigned used_mask, unsigned needed_count)
 
 
 /**
- * Assign locations for either VS inputs for FS outputs
+ * Assign locations for either VS inputs or FS outputs
  *
  * \param prog          Shader program whose variables need locations assigned
  * \param target_index  Selector for the program target to receive location
@@ -2065,7 +2117,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
             if (attr + slots > max_index) {
                linker_error(prog,
                            "insufficient contiguous locations "
-                           "available for %s `%s' %d %d %d", string,
+                           "available for %s `%s' %d %d %d\n", string,
                            var->name, used_locations, use_mask, attr);
                return false;
             }
@@ -2134,7 +2186,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
 
         linker_error(prog,
                      "insufficient contiguous locations "
-                     "available for %s `%s'",
+                     "available for %s `%s'\n",
                      string, to_assign[i].var->name);
         return false;
       }
@@ -2165,6 +2217,7 @@ demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
        * to have a location assigned.
        */
       if (var->data.is_unmatched_generic_inout) {
+         assert(var->data.mode != ir_var_temporary);
         var->data.mode = ir_var_auto;
       }
    }
@@ -2235,7 +2288,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
         continue;
 
       if (sh->num_samplers > ctx->Const.Program[i].MaxTextureImageUnits) {
-        linker_error(prog, "Too many %s shader texture samplers",
+        linker_error(prog, "Too many %s shader texture samplers\n",
                      _mesa_shader_stage_to_string(i));
       }
 
@@ -2249,7 +2302,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
                            _mesa_shader_stage_to_string(i));
          } else {
             linker_error(prog, "Too many %s shader default uniform block "
-                        "components",
+                        "components\n",
                          _mesa_shader_stage_to_string(i));
          }
       }
@@ -2262,7 +2315,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
                            "this is non-portable out-of-spec behavior\n",
                            _mesa_shader_stage_to_string(i));
          } else {
-            linker_error(prog, "Too many %s shader uniform components",
+            linker_error(prog, "Too many %s shader uniform components\n",
                          _mesa_shader_stage_to_string(i));
          }
       }
@@ -2280,7 +2333,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
       }
 
       if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) {
-        linker_error(prog, "Too many combined uniform blocks (%d/%d)",
+        linker_error(prog, "Too many combined uniform blocks (%d/%d)\n",
                      prog->NumUniformBlocks,
                      ctx->Const.MaxCombinedUniformBlocks);
       } else {
@@ -2288,7 +2341,7 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
             const unsigned max_uniform_blocks =
                ctx->Const.Program[i].MaxUniformBlocks;
            if (blocks[i] > max_uniform_blocks) {
-              linker_error(prog, "Too many %s uniform blocks (%d/%d)",
+              linker_error(prog, "Too many %s uniform blocks (%d/%d)\n",
                            _mesa_shader_stage_to_string(i),
                            blocks[i],
                            max_uniform_blocks);
@@ -2316,7 +2369,7 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
 
       if (sh) {
          if (sh->NumImages > ctx->Const.Program[i].MaxImageUniforms)
-            linker_error(prog, "Too many %s shader image uniforms",
+            linker_error(prog, "Too many %s shader image uniforms\n",
                          _mesa_shader_stage_to_string(i));
 
          total_image_units += sh->NumImages;
@@ -2332,11 +2385,11 @@ check_image_resources(struct gl_context *ctx, struct gl_shader_program *prog)
    }
 
    if (total_image_units > ctx->Const.MaxCombinedImageUniforms)
-      linker_error(prog, "Too many combined image uniforms");
+      linker_error(prog, "Too many combined image uniforms\n");
 
    if (total_image_units + fragment_outputs >
        ctx->Const.MaxCombinedImageUnitsAndFragmentOutputs)
-      linker_error(prog, "Too many combined image uniforms and fragment outputs");
+      linker_error(prog, "Too many combined image uniforms and fragment outputs\n");
 }
 
 
@@ -2360,7 +2413,7 @@ reserve_explicit_locations(struct gl_shader_program *prog,
                   max_loc + 1);
 
       if (!prog->UniformRemapTable) {
-         linker_error(prog, "Out of memory during linking.");
+         linker_error(prog, "Out of memory during linking.\n");
          return false;
       }
 
@@ -2389,8 +2442,8 @@ reserve_explicit_locations(struct gl_shader_program *prog,
           *     or linker error will be generated."
           */
          linker_error(prog,
-                      "location qualifier for uniform %s overlaps"
-                      "previously used location",
+                      "location qualifier for uniform %s overlaps "
+                      "previously used location\n",
                       var->name);
          return false;
       }
@@ -2425,7 +2478,7 @@ check_explicit_uniform_locations(struct gl_context *ctx,
    string_to_uint_map *uniform_map = new string_to_uint_map;
 
    if (!uniform_map) {
-      linker_error(prog, "Out of memory during linking.");
+      linker_error(prog, "Out of memory during linking.\n");
       return;
    }
 
@@ -2439,8 +2492,10 @@ check_explicit_uniform_locations(struct gl_context *ctx,
          ir_variable *var = node->as_variable();
          if ((var && var->data.mode == ir_var_uniform) &&
              var->data.explicit_location) {
-            if (!reserve_explicit_locations(prog, uniform_map, var))
+            if (!reserve_explicit_locations(prog, uniform_map, var)) {
+               delete uniform_map;
                return;
+            }
          }
       }
    }
@@ -2460,20 +2515,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
    prog->Validated = false;
    prog->_Used = false;
 
-   ralloc_free(prog->InfoLog);
-   prog->InfoLog = ralloc_strdup(NULL, "");
-
-   ralloc_free(prog->UniformBlocks);
-   prog->UniformBlocks = NULL;
-   prog->NumUniformBlocks = 0;
-   for (int i = 0; i < MESA_SHADER_STAGES; i++) {
-      ralloc_free(prog->UniformBlockStageIndex[i]);
-      prog->UniformBlockStageIndex[i] = NULL;
-   }
-
-   ralloc_free(prog->AtomicBuffers);
-   prog->AtomicBuffers = NULL;
-   prog->NumAtomicBuffers = 0;
    prog->ARB_fragment_coord_conventions_enable = false;
 
    /* Separate the shaders into groups based on their type.
@@ -2668,6 +2709,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
                                     &ctx->Const.ShaderCompilerOptions[i],
                                     ctx->Const.NativeIntegers))
         ;
+
+      lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir);
    }
 
    /* Check and validate stream emissions in geometry shaders */
@@ -2709,7 +2752,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
        */
       if (first == MESA_SHADER_FRAGMENT) {
          linker_error(prog, "Transform feedback varyings specified, but "
-                      "no vertex or geometry shader is present.");
+                      "no vertex or geometry shader is present.\n");
          goto done;
       }
 
@@ -2734,6 +2777,21 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
    if (last >= 0 && last < MESA_SHADER_FRAGMENT) {
       gl_shader *const sh = prog->_LinkedShaders[last];
 
+      if (first == MESA_SHADER_GEOMETRY) {
+         /* There was no vertex shader, but we still have to assign varying
+          * locations for use by geometry shader inputs in SSO.
+          *
+          * If the shader is not separable (i.e., prog->SeparateShader is
+          * false), linking will have already failed when first is
+          * MESA_SHADER_GEOMETRY.
+          */
+         if (!assign_varying_locations(ctx, mem_ctx, prog,
+                                       NULL, sh,
+                                       num_tfeedback_decls, tfeedback_decls,
+                                       prog->Geom.VerticesIn))
+            goto done;
+      }
+
       if (num_tfeedback_decls != 0 || prog->SeparateShader) {
          /* There was no fragment shader, but we still have to assign varying
           * locations for use by transform feedback.
@@ -2821,7 +2879,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
       goto done;
 
    update_array_sizes(prog);
-   link_assign_uniform_locations(prog);
+   link_assign_uniform_locations(prog, ctx->Const.UniformBooleanTrue);
    link_assign_atomic_counter_resources(ctx, prog);
    store_fragdepth_layout(prog);