#include "glsl_symbol_table.h"
#include "linker.h"
#include "main/macros.h"
+#include "main/mtypes.h"
#include "util/hash_table.h"
+#include "util/u_string.h"
namespace {
* interpolation qualifiers of variables of the same name do not
* match."
*/
- if (prog->IsES || prog->Version < 440)
+ if (prog->IsES || prog->data->Version < 440)
if (c->fields.structure[i].interpolation !=
p->fields.structure[i].interpolation)
return true;
* The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.2 spec
* says that sample need not match for varyings.
*/
- if (!prog->IsES || prog->Version < 310)
+ if (!prog->IsES || prog->data->Version < 310)
if (c->fields.structure[i].centroid !=
p->fields.structure[i].centroid)
return true;
*/
if ((a->data.how_declared != ir_var_declared_implicitly ||
b->data.how_declared != ir_var_declared_implicitly) &&
- (!prog->IsES || prog->Version != 310 ||
+ (!prog->IsES ||
interstage_member_mismatch(prog, a->get_interface_type(),
b->get_interface_type())))
return false;
/* If a block is an array then it must match across the shader.
* Unsized arrays are also processed and matched agaist sized arrays.
*/
- if (b->type != a->type &&
+ if (b->type != a->type && (b->type->is_array() || a->type->is_array()) &&
(b->is_interface_instance() || a->is_interface_instance()) &&
!validate_intrastage_arrays(prog, b, a))
return false;
if (var->data.explicit_location &&
var->data.location >= VARYING_SLOT_VAR0) {
char location_str[11];
- snprintf(location_str, 11, "%d", var->data.location);
+ util_snprintf(location_str, 11, "%d", var->data.location);
const struct hash_entry *entry =
_mesa_hash_table_search(ht, location_str);
* unsigned location value which is overkill but future proof.
*/
char location_str[11];
- snprintf(location_str, 11, "%d", var->data.location);
+ util_snprintf(location_str, 11, "%d", var->data.location);
_mesa_hash_table_insert(ht, ralloc_strdup(mem_ctx, location_str), var);
} else {
_mesa_hash_table_insert(ht,
consumer->Stage != MESA_SHADER_FRAGMENT) ||
consumer->Stage == MESA_SHADER_GEOMETRY;
+ /* Check that block re-declarations of gl_PerVertex are compatible
+ * across shaders: From OpenGL Shading Language 4.5, section
+ * "7.1 Built-In Language Variables", page 130 of the PDF:
+ *
+ * "If multiple shaders using members of a built-in block belonging
+ * to the same interface are linked together in the same program,
+ * they must all redeclare the built-in block in the same way, as
+ * described in section 4.3.9 “Interface Blocks” for interface-block
+ * matching, or a link-time error will result."
+ *
+ * This is done explicitly outside of iterating the member variable
+ * declarations because it is possible that the variables are not used and
+ * so they would have been optimised out.
+ */
+ const glsl_type *consumer_iface =
+ consumer->symbols->get_interface("gl_PerVertex",
+ ir_var_shader_in);
+
+ const glsl_type *producer_iface =
+ producer->symbols->get_interface("gl_PerVertex",
+ ir_var_shader_out);
+
+ if (producer_iface && consumer_iface &&
+ interstage_member_mismatch(prog, consumer_iface, producer_iface)) {
+ linker_error(prog, "Incompatible or missing gl_PerVertex re-declaration "
+ "in consecutive shaders");
+ return;
+ }
+
/* Add output interfaces from the producer to the symbol table. */
foreach_in_list(ir_instruction, node, producer->ir) {
ir_variable *var = node->as_variable();
* write to any of the pre-defined outputs (e.g. if the vertex shader
* does not write to gl_Position, etc), which is allowed and results in
* undefined behavior.
+ *
+ * From Section 4.3.4 (Inputs) of the GLSL 1.50 spec:
+ *
+ * "Only the input variables that are actually read need to be written
+ * by the previous stage; it is allowed to have superfluous
+ * declarations of input variables."
*/
if (producer_def == NULL &&
- !is_builtin_gl_in_block(var, consumer->Stage)) {
+ !is_builtin_gl_in_block(var, consumer->Stage) && var->data.used) {
linker_error(prog, "Input block `%s' is not an output of "
"the previous stage\n", var->get_interface_type()->name);
return;