glsl: Fix gl_shader_stage enum unsigned comparison
[mesa.git] / src / compiler / glsl / link_varyings.cpp
index 8cd364441d3fc4960bc5cc29201038e441005118..910e2eda82b877c15a15b50c89f218cb3073805b 100644 (file)
@@ -745,10 +745,12 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
       unsigned actual_array_size;
       switch (this->lowered_builtin_array_variable) {
       case clip_distance:
-         actual_array_size = prog->LastClipDistanceArraySize;
+         actual_array_size = prog->last_vert_prog ?
+            prog->last_vert_prog->info.clip_distance_array_size : 0;
          break;
       case cull_distance:
-         actual_array_size = prog->LastCullDistanceArraySize;
+         actual_array_size = prog->last_vert_prog ?
+            prog->last_vert_prog->info.cull_distance_array_size : 0;
          break;
       case tess_level_outer:
          actual_array_size = 4;
@@ -1076,6 +1078,9 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
                      unsigned num_tfeedback_decls,
                      tfeedback_decl *tfeedback_decls, bool has_xfb_qualifiers)
 {
+   if (!prog->last_vert_prog)
+      return true;
+
    /* Make sure MaxTransformFeedbackBuffers is less than 32 so the bitmask for
     * tracking the number of buffers doesn't overflow.
     */
@@ -1084,7 +1089,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
    bool separate_attribs_mode =
       prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
 
-   struct gl_program *xfb_prog = prog->xfb_program;
+   struct gl_program *xfb_prog = prog->last_vert_prog;
    xfb_prog->sh.LinkedTransformFeedback =
       rzalloc(xfb_prog, struct gl_transform_feedback_info);
 
@@ -1212,6 +1217,7 @@ class varying_matches
 {
 public:
    varying_matches(bool disable_varying_packing, bool xfb_enabled,
+                   bool enhanced_layouts_enabled,
                    gl_shader_stage producer_stage,
                    gl_shader_stage consumer_stage);
    ~varying_matches();
@@ -1245,6 +1251,8 @@ private:
     */
    const bool xfb_enabled;
 
+   const bool enhanced_layouts_enabled;
+
    /**
     * Enum representing the order in which varyings are packed within a
     * packing class.
@@ -1321,10 +1329,12 @@ private:
 
 varying_matches::varying_matches(bool disable_varying_packing,
                                  bool xfb_enabled,
+                                 bool enhanced_layouts_enabled,
                                  gl_shader_stage producer_stage,
                                  gl_shader_stage consumer_stage)
    : disable_varying_packing(disable_varying_packing),
      xfb_enabled(xfb_enabled),
+     enhanced_layouts_enabled(enhanced_layouts_enabled),
      producer_stage(producer_stage),
      consumer_stage(consumer_stage)
 {
@@ -1402,7 +1412,7 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
 
    if (!disable_varying_packing &&
        (needs_flat_qualifier ||
-        (consumer_stage != -1 && consumer_stage != MESA_SHADER_FRAGMENT))) {
+        (consumer_stage != MESA_SHADER_NONE && consumer_stage != MESA_SHADER_FRAGMENT))) {
       /* Since this varying is not being consumed by the fragment shader, its
        * interpolation type varying cannot possibly affect rendering.
        * Also, this variable is non-flat and is (or contains) an integer
@@ -1456,17 +1466,24 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
       ? consumer_stage : producer_stage;
    const glsl_type *type = get_varying_type(var, stage);
 
+   if (producer_var && consumer_var &&
+       consumer_var->data.must_be_shader_input) {
+      producer_var->data.must_be_shader_input = 1;
+   }
+
    this->matches[this->num_matches].packing_class
       = this->compute_packing_class(var);
    this->matches[this->num_matches].packing_order
       = this->compute_packing_order(var);
-   if (this->disable_varying_packing && !is_varying_packing_safe(type, var)) {
+   if ((this->disable_varying_packing && !is_varying_packing_safe(type, var)) ||
+       var->data.must_be_shader_input) {
       unsigned slots = type->count_attribute_slots(false);
       this->matches[this->num_matches].num_components = slots * 4;
    } else {
       this->matches[this->num_matches].num_components
          = type->component_slots();
    }
+
    this->matches[this->num_matches].producer_var = producer_var;
    this->matches[this->num_matches].consumer_var = consumer_var;
    this->num_matches++;
@@ -1539,7 +1556,8 @@ varying_matches::assign_locations(struct gl_shader_program *prog,
        * we can pack varyings together that are only used for transform
        * feedback.
        */
-      if ((this->disable_varying_packing &&
+      if (var->data.must_be_shader_input ||
+          (this->disable_varying_packing &&
            !(previous_var_xfb_only && var->data.is_xfb_only)) ||
           (i > 0 && this->matches[i - 1].packing_class
           != this->matches[i].packing_class )) {
@@ -1609,6 +1627,12 @@ varying_matches::assign_locations(struct gl_shader_program *prog,
 void
 varying_matches::store_locations() const
 {
+   /* Check is location needs to be packed with lower_packed_varyings() or if
+    * we can just use ARB_enhanced_layouts packing.
+    */
+   bool pack_loc[MAX_VARYINGS_INCL_PATCH] = { 0 };
+   const glsl_type *loc_type[MAX_VARYINGS_INCL_PATCH][4] = { {NULL, NULL} };
+
    for (unsigned i = 0; i < this->num_matches; i++) {
       ir_variable *producer_var = this->matches[i].producer_var;
       ir_variable *consumer_var = this->matches[i].consumer_var;
@@ -1626,6 +1650,64 @@ varying_matches::store_locations() const
          consumer_var->data.location = VARYING_SLOT_VAR0 + slot;
          consumer_var->data.location_frac = offset;
       }
+
+      /* Find locations suitable for native packing via
+       * ARB_enhanced_layouts.
+       */
+      if (producer_var && consumer_var) {
+         if (enhanced_layouts_enabled) {
+            const glsl_type *type =
+               get_varying_type(producer_var, producer_stage);
+            if (type->is_array() || type->is_matrix() || type->is_record() ||
+                type->is_double()) {
+               unsigned comp_slots = type->component_slots() + offset;
+               unsigned slots = comp_slots / 4;
+               if (comp_slots % 4)
+                  slots += 1;
+
+               for (unsigned j = 0; j < slots; j++) {
+                  pack_loc[slot + j] = true;
+               }
+            } else if (offset + type->vector_elements > 4) {
+               pack_loc[slot] = true;
+               pack_loc[slot + 1] = true;
+            } else {
+               loc_type[slot][offset] = type;
+            }
+         }
+      }
+   }
+
+   /* Attempt to use ARB_enhanced_layouts for more efficient packing if
+    * suitable.
+    */
+   if (enhanced_layouts_enabled) {
+      for (unsigned i = 0; i < this->num_matches; i++) {
+         ir_variable *producer_var = this->matches[i].producer_var;
+         ir_variable *consumer_var = this->matches[i].consumer_var;
+         unsigned generic_location = this->matches[i].generic_location;
+         unsigned slot = generic_location / 4;
+
+         if (pack_loc[slot] || !producer_var || !consumer_var)
+            continue;
+
+         const glsl_type *type =
+            get_varying_type(producer_var, producer_stage);
+         bool type_match = true;
+         for (unsigned j = 0; j < 4; j++) {
+            if (loc_type[slot][j]) {
+               if (type->base_type != loc_type[slot][j]->base_type)
+                  type_match = false;
+            }
+         }
+
+         if (type_match) {
+            producer_var->data.explicit_location = 1;
+            consumer_var->data.explicit_location = 1;
+            producer_var->data.explicit_component = 1;
+            consumer_var->data.explicit_component = 1;
+         }
+      }
    }
 }
 
@@ -1655,8 +1737,9 @@ varying_matches::compute_packing_class(const ir_variable *var)
     * Therefore, the packing class depends only on the interpolation type.
     */
    unsigned packing_class = var->data.centroid | (var->data.sample << 1) |
-                            (var->data.patch << 2);
-   packing_class *= 4;
+                            (var->data.patch << 2) |
+                            (var->data.must_be_shader_input << 3);
+   packing_class *= 8;
    packing_class += var->is_interpolation_flat()
       ? unsigned(INTERP_MODE_FLAT) : var->data.interpolation;
    return packing_class;
@@ -1673,7 +1756,7 @@ varying_matches::compute_packing_order(const ir_variable *var)
 {
    const glsl_type *element_type = var->type;
 
-   while (element_type->base_type == GLSL_TYPE_ARRAY) {
+   while (element_type->is_array()) {
       element_type = element_type->fields.array;
    }
 
@@ -2086,8 +2169,9 @@ assign_varying_locations(struct gl_context *ctx,
       disable_varying_packing = true;
 
    varying_matches matches(disable_varying_packing, xfb_enabled,
-                           producer ? producer->Stage : (gl_shader_stage)-1,
-                           consumer ? consumer->Stage : (gl_shader_stage)-1);
+                           ctx->Extensions.ARB_enhanced_layouts,
+                           producer ? producer->Stage : MESA_SHADER_NONE,
+                           consumer ? consumer->Stage : MESA_SHADER_NONE);
    hash_table *tfeedback_candidates =
          _mesa_hash_table_create(NULL, _mesa_key_hash_string,
                                  _mesa_key_string_equal);