#include "linker.h"
#include "link_varyings.h"
#include "main/macros.h"
-#include "program/hash_table.h"
+#include "util/hash_table.h"
#include "program.h"
return;
}
- if (!prog->IsES && input->data.invariant != output->data.invariant) {
+ /* The GLSL 4.30 and GLSL ES 3.00 specifications say:
+ *
+ * "As only outputs need be declared with invariant, an output from
+ * one shader stage will still match an input of a subsequent stage
+ * without the input being declared as invariant."
+ *
+ * while GLSL 4.20 says:
+ *
+ * "For variables leaving one shader and coming into another shader,
+ * the invariant keyword has to be used in both shaders, or a link
+ * error will result."
+ *
+ * and GLSL ES 1.00 section 4.6.4 "Invariance and Linking" says:
+ *
+ * "The invariance of varyings that are declared in both the vertex
+ * and fragment shaders must match."
+ */
+ if (input->data.invariant != output->data.invariant &&
+ prog->Version < (prog->IsES ? 300 : 430)) {
linker_error(prog,
"%s shader output `%s' %s invariant qualifier, "
"but %s shader input %s invariant qualifier\n",
*/
if (var->data.is_unmatched_generic_inout && !var->data.is_xfb_only) {
assert(var->data.mode != ir_var_temporary);
+
+ /* Assign zeros to demoted inputs to allow more optimizations. */
+ if (var->data.mode == ir_var_shader_in && !var->constant_value)
+ var->constant_value = ir_constant::zero(var, var->type);
+
var->data.mode = ir_var_auto;
}
}
name = "gl_TessLevelInnerMESA";
break;
}
- this->matched_candidate = (const tfeedback_candidate *)
- hash_table_find(tfeedback_candidates, name);
+ hash_entry *entry = _mesa_hash_table_search(tfeedback_candidates, name);
+
+ this->matched_candidate = entry ?
+ (const tfeedback_candidate *) entry->data : NULL;
+
if (!this->matched_candidate) {
/* From GL_EXT_transform_feedback:
* A program will fail to link if:
linker_error(prog, "Transform feedback varying %s undeclared.",
this->orig_name);
}
+
return this->matched_candidate;
}
(producer_var->type->contains_integer() ||
producer_var->type->contains_double());
- if (needs_flat_qualifier ||
- (consumer_stage != -1 && consumer_stage != MESA_SHADER_FRAGMENT)) {
+ if (!disable_varying_packing &&
+ (needs_flat_qualifier ||
+ (consumer_stage != -1 && 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
if (producer_var) {
producer_var->data.centroid = false;
producer_var->data.sample = false;
- producer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
+ producer_var->data.interpolation = INTERP_MODE_FLAT;
}
if (consumer_var) {
consumer_var->data.centroid = false;
consumer_var->data.sample = false;
- consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
+ consumer_var->data.interpolation = INTERP_MODE_FLAT;
}
}
sizeof(*this->matches) * this->matches_capacity);
}
- const ir_variable *const var = (producer_var != NULL)
- ? producer_var : consumer_var;
- const gl_shader_stage stage = (producer_var != NULL)
- ? producer_stage : consumer_stage;
+ /* We must use the consumer to compute the packing class because in GL4.4+
+ * there is no guarantee interpolation qualifiers will match across stages.
+ *
+ * From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.30 spec:
+ *
+ * "The type and presence of interpolation qualifiers of variables with
+ * the same name declared in all linked shaders for the same cross-stage
+ * interface must match, otherwise the link command will fail.
+ *
+ * When comparing an output from one stage to an input of a subsequent
+ * stage, the input and output don't match if their interpolation
+ * qualifiers (or lack thereof) are not the same."
+ *
+ * This text was also in at least revison 7 of the 4.40 spec but is no
+ * longer in revision 9 and not in the 4.50 spec.
+ */
+ const ir_variable *const var = (consumer_var != NULL)
+ ? consumer_var : producer_var;
+ const gl_shader_stage stage = (consumer_var != NULL)
+ ? consumer_stage : producer_stage;
const glsl_type *type = get_varying_type(var, stage);
this->matches[this->num_matches].packing_class
unsigned packing_class = var->data.centroid | (var->data.sample << 1) |
(var->data.patch << 2);
packing_class *= 4;
- packing_class += var->data.interpolation;
+ packing_class += var->is_interpolation_flat()
+ ? unsigned(INTERP_MODE_FLAT) : var->data.interpolation;
return packing_class;
}
candidate->toplevel_var = this->toplevel_var;
candidate->type = type;
candidate->offset = this->varying_floats;
- hash_table_insert(this->tfeedback_candidates, candidate,
- ralloc_strdup(this->mem_ctx, name));
+ _mesa_hash_table_insert(this->tfeedback_candidates,
+ ralloc_strdup(this->mem_ctx, name),
+ candidate);
this->varying_floats += type->component_slots();
}
ralloc_asprintf(mem_ctx, "%s.%s",
input_var->get_interface_type()->without_array()->name,
input_var->name);
- hash_table_insert(consumer_interface_inputs, input_var,
- iface_field_name);
+ _mesa_hash_table_insert(consumer_interface_inputs,
+ iface_field_name, input_var);
} else {
- hash_table_insert(consumer_inputs, input_var,
- ralloc_strdup(mem_ctx, input_var->name));
+ _mesa_hash_table_insert(consumer_inputs,
+ ralloc_strdup(mem_ctx, input_var->name),
+ input_var);
}
}
}
ralloc_asprintf(mem_ctx, "%s.%s",
output_var->get_interface_type()->without_array()->name,
output_var->name);
- input_var =
- (ir_variable *) hash_table_find(consumer_interface_inputs,
- iface_field_name);
+ hash_entry *entry = _mesa_hash_table_search(consumer_interface_inputs, iface_field_name);
+ input_var = entry ? (ir_variable *) entry->data : NULL;
} else {
- input_var =
- (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
+ hash_entry *entry = _mesa_hash_table_search(consumer_inputs, output_var->name);
+ input_var = entry ? (ir_variable *) entry->data : NULL;
}
return (input_var == NULL || input_var->data.mode != ir_var_shader_in)
bool xfb_enabled =
ctx->Extensions.EXT_transform_feedback && !unpackable_tess;
- /* Disable varying packing for GL 4.4+ as there is no guarantee
- * that interpolation qualifiers will match between shaders in these
- * versions. We also disable packing on outward facing interfaces for
- * SSO because in ES we need to retain the unpacked varying information
- * for draw time validation. For desktop GL we could allow packing for
- * versions < 4.4 but it's just safer not to do packing.
+ /* Disable packing on outward facing interfaces for SSO because in ES we
+ * need to retain the unpacked varying information for draw time
+ * validation.
*
* Packing is still enabled on individual arrays, structs, and matrices as
* these are required by the transform feedback code and it is still safe
* to do so. We also enable packing when a varying is only used for
* transform feedback and its not a SSO.
- *
- * Varying packing currently only packs together varyings with matching
- * interpolation qualifiers as the backends assume all packed components
- * are to be processed in the same way. Therefore we cannot do packing in
- * these versions of GL without the risk of mismatching interfaces.
- *
- * From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.30 spec:
- *
- * "The type and presence of interpolation qualifiers of variables with
- * the same name declared in all linked shaders for the same cross-stage
- * interface must match, otherwise the link command will fail.
- *
- * When comparing an output from one stage to an input of a subsequent
- * stage, the input and output don't match if their interpolation
- * qualifiers (or lack thereof) are not the same."
- *
- * This text was also in at least revison 7 of the 4.40 spec but is no
- * longer in revision 9 and not in the 4.50 spec.
*/
bool disable_varying_packing =
ctx->Const.DisableVaryingPacking || unpackable_tess;
- if ((ctx->API == API_OPENGL_CORE && ctx->Version >= 44) ||
- (prog->SeparateShader && (producer == NULL || consumer == NULL)))
+ if (prog->SeparateShader && (producer == NULL || consumer == NULL))
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);
- hash_table *tfeedback_candidates
- = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
- hash_table *consumer_inputs
- = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
- hash_table *consumer_interface_inputs
- = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
+ hash_table *tfeedback_candidates =
+ _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
+ hash_table *consumer_inputs =
+ _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
+ hash_table *consumer_interface_inputs =
+ _mesa_hash_table_create(NULL, _mesa_key_hash_string,
+ _mesa_key_string_equal);
ir_variable *consumer_inputs_with_locations[VARYING_SLOT_TESS_MAX] = {
NULL,
};
}
}
+ _mesa_hash_table_destroy(consumer_inputs, NULL);
+ _mesa_hash_table_destroy(consumer_interface_inputs, NULL);
+
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
if (!tfeedback_decls[i].is_varying())
continue;
= tfeedback_decls[i].find_candidate(prog, tfeedback_candidates);
if (matched_candidate == NULL) {
- hash_table_dtor(tfeedback_candidates);
- hash_table_dtor(consumer_inputs);
- hash_table_dtor(consumer_interface_inputs);
+ _mesa_hash_table_destroy(tfeedback_candidates, NULL);
return false;
}
continue;
if (!tfeedback_decls[i].assign_location(ctx, prog)) {
- hash_table_dtor(tfeedback_candidates);
- hash_table_dtor(consumer_inputs);
- hash_table_dtor(consumer_interface_inputs);
+ _mesa_hash_table_destroy(tfeedback_candidates, NULL);
return false;
}
}
-
- hash_table_dtor(tfeedback_candidates);
- hash_table_dtor(consumer_inputs);
- hash_table_dtor(consumer_interface_inputs);
+ _mesa_hash_table_destroy(tfeedback_candidates, NULL);
if (consumer && producer) {
foreach_in_list(ir_instruction, node, consumer->ir) {