/* Only assign locations for generic attributes / varyings / etc.
*/
- if (var->location >= generic_base)
+ if ((var->location >= generic_base) && !var->explicit_location)
var->location = -1;
}
}
}
}
+ if (var->explicit_location) {
+ if (existing->explicit_location
+ && (var->location != existing->location)) {
+ linker_error_printf(prog, "explicit locations for %s "
+ "`%s' have differing values\n",
+ mode_string(var), var->name);
+ return false;
+ }
+
+ existing->location = var->location;
+ existing->explicit_location = true;
+ }
+
/* FINISHME: Handle non-constant initializers.
*/
if (var->constant_value != NULL) {
*/
if (input->type != output->type) {
linker_error_printf(prog,
- "%s shader output `%s' delcared as "
+ "%s shader output `%s' declared as "
"type `%s', but %s shader input declared "
"as type `%s'\n",
producer_stage, output->name,
*/
static void
-update_uniform_array_sizes(struct gl_shader_program *prog)
+update_array_sizes(struct gl_shader_program *prog)
{
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
foreach_list(node, prog->_LinkedShaders[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_uniform) ||
+ if ((var == NULL) || (var->mode != ir_var_uniform &&
+ var->mode != ir_var_in &&
+ var->mode != ir_var_out) ||
!var->type->is_array())
continue;
}
}
}
+
if (size + 1 != var->type->fields.array->length) {
var->type = glsl_type::get_array_instance(var->type->fields.array,
size + 1);
hash_table_string_compare);
void *mem_ctx = talloc_new(NULL);
- update_uniform_array_sizes(prog);
-
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
unsigned next_position = 0;
if ((var == NULL) || (var->mode != ir_var_in))
continue;
+ if (var->explicit_location) {
+ const unsigned slots = count_attribute_slots(var->type);
+ const unsigned use_mask = (1 << slots) - 1;
+ const int attr = var->location - VERT_ATTRIB_GENERIC0;
+
+ if ((var->location >= (int)(max_attribute_index + VERT_ATTRIB_GENERIC0))
+ || (var->location < 0)) {
+ linker_error_printf(prog,
+ "invalid explicit location %d specified for "
+ "`%s'\n",
+ (var->location < 0) ? var->location : attr,
+ var->name);
+ return false;
+ } else if (var->location >= VERT_ATTRIB_GENERIC0) {
+ used_locations |= (use_mask << attr);
+ }
+ }
+
/* The location was explicitly assigned, nothing to do here.
*/
if (var->location != -1)
;
}
+ update_array_sizes(prog);
+
assign_uniform_locations(prog);
if (prog->_NumLinkedShaders && prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER) {
* FINISHME: GL_MAX_VERTEX_ATTRIBS. GL_MAX_VERTEX_ATTRIBS must be
* FINISHME: at least 16, so hardcode 16 for now.
*/
- if (!assign_attribute_locations(prog, 16))
+ if (!assign_attribute_locations(prog, 16)) {
+ prog->LinkStatus = false;
goto done;
+ }
if (prog->_NumLinkedShaders == 1)
demote_unread_shader_outputs(prog->_LinkedShaders[0]);