return false;
}
- const unsigned slots = var->type->count_attribute_slots(target_index == MESA_SHADER_VERTEX ? true : false);
+ const unsigned slots = var->type->count_attribute_slots(target_index == MESA_SHADER_VERTEX);
/* If the variable is not a built-in and has a location statically
* assigned in the shader (presumably via a layout qualifier), make sure
*/
static gl_shader_variable *
create_shader_variable(struct gl_shader_program *shProg,
- const ir_variable *in, bool use_implicit_location,
- int location_bias)
+ const ir_variable *in,
+ const char *name, const glsl_type *type,
+ bool use_implicit_location, int location)
{
gl_shader_variable *out = ralloc(shProg, struct gl_shader_variable);
if (!out)
in->data.location == SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) {
out->name = ralloc_strdup(shProg, "gl_VertexID");
} else {
- out->name = ralloc_strdup(shProg, in->name);
+ out->name = ralloc_strdup(shProg, name);
}
if (!out->name)
!(in->data.explicit_location || use_implicit_location)) {
out->location = -1;
} else {
- out->location = in->data.location - location_bias;
+ out->location = location;
}
- out->type = in->type;
+ out->type = type;
out->index = in->data.index;
out->patch = in->data.patch;
out->mode = in->data.mode;
static bool
add_shader_variable(struct gl_shader_program *shProg, unsigned stage_mask,
GLenum programInterface, ir_variable *var,
- bool use_implicit_location, int location_bias)
+ const char *name, const glsl_type *type,
+ bool use_implicit_location, int location)
{
- gl_shader_variable *sha_v =
- create_shader_variable(shProg, var, use_implicit_location, location_bias);
- if (!sha_v)
- return false;
+ const bool is_vertex_input =
+ programInterface == GL_PROGRAM_INPUT &&
+ stage_mask == MESA_SHADER_VERTEX;
+
+ switch (type->base_type) {
+ case GLSL_TYPE_STRUCT: {
+ /* From the ARB_program_interface_query specification:
+ *
+ * "For an active variable declared as a structure, a separate entry
+ * will be generated for each active structure member. The name of
+ * each entry is formed by concatenating the name of the structure,
+ * the "." character, and the name of the structure member. If a
+ * structure member to enumerate is itself a structure or array, these
+ * enumeration rules are applied recursively."
+ */
+ unsigned field_location = location;
+ for (unsigned i = 0; i < type->length; i++) {
+ const struct glsl_struct_field *field = &type->fields.structure[i];
+ char *field_name = ralloc_asprintf(shProg, "%s.%s", name, field->name);
+ if (!add_shader_variable(shProg, stage_mask, programInterface,
+ var, field_name, field->type,
+ use_implicit_location, field_location))
+ return false;
+
+ field_location +=
+ field->type->count_attribute_slots(is_vertex_input);
+ }
+ return true;
+ }
+
+ default: {
+ /* From the ARB_program_interface_query specification:
+ *
+ * "For an active variable declared as a single instance of a basic
+ * type, a single entry will be generated, using the variable name
+ * from the shader source."
+ */
+ gl_shader_variable *sha_v =
+ create_shader_variable(shProg, var, name, type,
+ use_implicit_location, location);
+ if (!sha_v)
+ return false;
- return add_program_resource(shProg, programInterface, sha_v, stage_mask);
+ return add_program_resource(shProg, programInterface, sha_v, stage_mask);
+ }
+ }
}
static bool
(stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_out);
if (!add_shader_variable(shProg, 1 << stage, programInterface,
- var, vs_input_or_fs_output, loc_bias))
+ var, var->name, var->type, vs_input_or_fs_output,
+ var->data.location - loc_bias))
return false;
}
return true;
const int stage_mask =
build_stageref(shProg, var->name, var->data.mode);
if (!add_shader_variable(shProg, stage_mask,
- iface, var, false, VARYING_SLOT_VAR0))
+ iface, var, var->name, var->type, false,
+ var->data.location - VARYING_SLOT_VAR0))
return false;
}
}
if (!add_shader_variable(shProg,
1 << MESA_SHADER_FRAGMENT,
- GL_PROGRAM_OUTPUT, var, true, FRAG_RESULT_DATA0))
+ GL_PROGRAM_OUTPUT, var, var->name, var->type,
+ true, var->data.location - FRAG_RESULT_DATA0))
return false;
}
}