/* Check that all of the qualifiers match between stages.
*/
- if (input->centroid != output->centroid) {
+ if (input->data.centroid != output->data.centroid) {
linker_error(prog,
"%s shader output `%s' %s centroid qualifier, "
"but %s shader input %s centroid qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- (output->centroid) ? "has" : "lacks",
+ (output->data.centroid) ? "has" : "lacks",
_mesa_glsl_shader_target_name(consumer_type),
- (input->centroid) ? "has" : "lacks");
+ (input->data.centroid) ? "has" : "lacks");
return;
}
- if (input->invariant != output->invariant) {
+ if (input->data.sample != output->data.sample) {
+ linker_error(prog,
+ "%s shader output `%s' %s sample qualifier, "
+ "but %s shader input %s sample qualifier\n",
+ _mesa_glsl_shader_target_name(producer_type),
+ output->name,
+ (output->data.sample) ? "has" : "lacks",
+ _mesa_glsl_shader_target_name(consumer_type),
+ (input->data.sample) ? "has" : "lacks");
+ return;
+ }
+
+ if (input->data.invariant != output->data.invariant) {
linker_error(prog,
"%s shader output `%s' %s invariant qualifier, "
"but %s shader input %s invariant qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- (output->invariant) ? "has" : "lacks",
+ (output->data.invariant) ? "has" : "lacks",
_mesa_glsl_shader_target_name(consumer_type),
- (input->invariant) ? "has" : "lacks");
+ (input->data.invariant) ? "has" : "lacks");
return;
}
- if (input->interpolation != output->interpolation) {
+ if (input->data.interpolation != output->data.interpolation) {
linker_error(prog,
"%s shader output `%s' specifies %s "
"interpolation qualifier, "
"interpolation qualifier\n",
_mesa_glsl_shader_target_name(producer_type),
output->name,
- output->interpolation_string(),
+ interpolation_string(output->data.interpolation),
_mesa_glsl_shader_target_name(consumer_type),
- input->interpolation_string());
+ interpolation_string(input->data.interpolation));
return;
}
}
GLenum consumer_type,
GLenum producer_type)
{
- if (front_color != NULL && front_color->assigned)
+ if (front_color != NULL && front_color->data.assigned)
cross_validate_types_and_qualifiers(prog, input, front_color,
consumer_type, producer_type);
- if (back_color != NULL && back_color->assigned)
+ if (back_color != NULL && back_color->data.assigned)
cross_validate_types_and_qualifiers(prog, input, back_color,
consumer_type, producer_type);
}
foreach_list(node, producer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_shader_out))
+ if ((var == NULL) || (var->data.mode != ir_var_shader_out))
continue;
parameters.add_variable(var);
foreach_list(node, consumer->ir) {
ir_variable *const input = ((ir_instruction *) node)->as_variable();
- if ((input == NULL) || (input->mode != ir_var_shader_in))
+ if ((input == NULL) || (input->data.mode != ir_var_shader_in))
continue;
- if (strcmp(input->name, "gl_Color") == 0 && input->used) {
+ if (strcmp(input->name, "gl_Color") == 0 && input->data.used) {
const ir_variable *const front_color =
parameters.get_variable("gl_FrontColor");
cross_validate_front_and_back_color(prog, input,
front_color, back_color,
consumer->Type, producer->Type);
- } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->used) {
+ } else if (strcmp(input->name, "gl_SecondaryColor") == 0 && input->data.used) {
const ir_variable *const front_color =
parameters.get_variable("gl_FrontSecondaryColor");
* will fail to find any matching variable.
*/
void
-tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
- const void *mem_ctx, const char *input)
+tfeedback_decl::init(struct gl_context *ctx, const void *mem_ctx,
+ const char *input)
{
/* We don't have to be pedantic about what is a valid GLSL variable name,
* because any variable with an invalid name can't exist in the IR anyway.
assert(this->is_varying());
unsigned fine_location
- = this->matched_candidate->toplevel_var->location * 4
- + this->matched_candidate->toplevel_var->location_frac
+ = this->matched_candidate->toplevel_var->data.location * 4
+ + this->matched_candidate->toplevel_var->data.location_frac
+ this->matched_candidate->offset;
if (this->matched_candidate->type->is_array()) {
const unsigned vector_elements =
this->matched_candidate->type->fields.array->vector_elements;
unsigned actual_array_size = this->is_clip_distance_mesa ?
- prog->Vert.ClipDistanceArraySize :
+ prog->LastClipDistanceArraySize :
this->matched_candidate->type->array_size();
if (this->is_subscripted) {
char **varying_names, tfeedback_decl *decls)
{
for (unsigned i = 0; i < num_names; ++i) {
- decls[i].init(ctx, prog, mem_ctx, varying_names[i]);
+ decls[i].init(ctx, mem_ctx, varying_names[i]);
if (!decls[i].is_varying())
continue;
return true;
}
+namespace {
/**
* Data structure recording the relationship between outputs of one shader
const bool consumer_is_fs;
};
+} /* anonymous namespace */
varying_matches::varying_matches(bool disable_varying_packing,
bool consumer_is_fs)
void
varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
{
- if (!producer_var->is_unmatched_generic_inout) {
+ if (!producer_var->data.is_unmatched_generic_inout) {
/* Either a location already exists for this variable (since it is part
* of fixed functionality), or it has already been recorded as part of a
* previous match.
* regardless of where they appear. We can trivially satisfy that
* requirement by changing the interpolation type to flat here.
*/
- producer_var->centroid = false;
- producer_var->interpolation = INTERP_QUALIFIER_FLAT;
+ producer_var->data.centroid = false;
+ producer_var->data.sample = false;
+ producer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
if (consumer_var) {
- consumer_var->centroid = false;
- consumer_var->interpolation = INTERP_QUALIFIER_FLAT;
+ consumer_var->data.centroid = false;
+ consumer_var->data.sample = false;
+ consumer_var->data.interpolation = INTERP_QUALIFIER_FLAT;
}
}
this->matches[this->num_matches].producer_var = producer_var;
this->matches[this->num_matches].consumer_var = consumer_var;
this->num_matches++;
- producer_var->is_unmatched_generic_inout = 0;
+ producer_var->data.is_unmatched_generic_inout = 0;
if (consumer_var)
- consumer_var->is_unmatched_generic_inout = 0;
+ consumer_var->data.is_unmatched_generic_inout = 0;
}
unsigned slot = generic_location / 4;
unsigned offset = generic_location % 4;
- producer_var->location = producer_base + slot;
- producer_var->location_frac = offset;
+ producer_var->data.location = producer_base + slot;
+ producer_var->data.location_frac = offset;
if (consumer_var) {
- assert(consumer_var->location == -1);
- consumer_var->location = consumer_base + slot;
- consumer_var->location_frac = offset;
+ assert(consumer_var->data.location == -1);
+ consumer_var->data.location = consumer_base + slot;
+ consumer_var->data.location_frac = offset;
}
}
}
*
* Therefore, the packing class depends only on the interpolation type.
*/
- unsigned packing_class = var->centroid ? 1 : 0;
+ unsigned packing_class = var->data.centroid | (var->data.sample << 1);
packing_class *= 4;
- packing_class += var->interpolation;
+ packing_class += var->data.interpolation;
return packing_class;
}
{
/* Only fragment shaders will take a varying variable as an input */
if (shaderType == GL_FRAGMENT_SHADER &&
- var->mode == ir_var_shader_in) {
- switch (var->location) {
+ var->data.mode == ir_var_shader_in) {
+ switch (var->data.location) {
case VARYING_SLOT_POS:
case VARYING_SLOT_FACE:
case VARYING_SLOT_PNTC:
this->toplevel_var = var;
this->varying_floats = 0;
if (var->is_interface_instance())
- program_resource_visitor::process(var->interface_type,
- var->interface_type->name);
+ program_resource_visitor::process(var->get_interface_type(),
+ var->get_interface_type()->name);
else
program_resource_visitor::process(var);
}
ir_variable *const input_var =
((ir_instruction *) node)->as_variable();
- if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) {
- if (input_var->interface_type != NULL) {
+ if ((input_var != NULL) && (input_var->data.mode == ir_var_shader_in)) {
+ if (input_var->get_interface_type() != NULL) {
char *const iface_field_name =
ralloc_asprintf(mem_ctx, "%s.%s",
- input_var->interface_type->name,
+ input_var->get_interface_type()->name,
input_var->name);
hash_table_insert(consumer_interface_inputs, input_var,
iface_field_name);
foreach_list(node, producer->ir) {
ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
- if ((output_var == NULL) || (output_var->mode != ir_var_shader_out))
+ if ((output_var == NULL) || (output_var->data.mode != ir_var_shader_out))
continue;
tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
g.process(output_var);
ir_variable *input_var;
- if (output_var->interface_type != NULL) {
+ if (output_var->get_interface_type() != NULL) {
char *const iface_field_name =
ralloc_asprintf(mem_ctx, "%s.%s",
- output_var->interface_type->name,
+ output_var->get_interface_type()->name,
output_var->name);
input_var =
(ir_variable *) hash_table_find(consumer_interface_inputs,
(ir_variable *) hash_table_find(consumer_inputs, output_var->name);
}
- if (input_var && input_var->mode != ir_var_shader_in)
+ if (input_var && input_var->data.mode != ir_var_shader_in)
input_var = NULL;
if (input_var) {
return false;
}
- if (matched_candidate->toplevel_var->is_unmatched_generic_inout)
+ if (matched_candidate->toplevel_var->data.is_unmatched_generic_inout)
matches.record(matched_candidate->toplevel_var, NULL);
}
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var && var->mode == ir_var_shader_in &&
- var->is_unmatched_generic_inout) {
+ if (var && var->data.mode == ir_var_shader_in &&
+ var->data.is_unmatched_generic_inout) {
if (prog->Version <= 120) {
/* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
*
/* An 'in' variable is only really a shader input if its
* value is written by the previous stage.
*/
- var->mode = ir_var_auto;
+ var->data.mode = ir_var_auto;
}
}
}
}
bool
-check_against_varying_limit(struct gl_context *ctx,
- struct gl_shader_program *prog,
- gl_shader *consumer)
+check_against_output_limit(struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ gl_shader *producer)
+{
+ unsigned output_vectors = 0;
+
+ foreach_list(node, producer->ir) {
+ ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+ if (var && var->data.mode == ir_var_shader_out &&
+ is_varying_var(producer->Type, var)) {
+ output_vectors += var->type->count_attribute_slots();
+ }
+ }
+
+ unsigned max_output_components;
+ switch (producer->Type) {
+ case GL_VERTEX_SHADER:
+ max_output_components = ctx->Const.VertexProgram.MaxOutputComponents;
+ break;
+ case GL_GEOMETRY_SHADER:
+ max_output_components = ctx->Const.GeometryProgram.MaxOutputComponents;
+ break;
+ case GL_FRAGMENT_SHADER:
+ default:
+ assert(!"Should not get here.");
+ return false;
+ }
+
+ const unsigned output_components = output_vectors * 4;
+ if (output_components > max_output_components) {
+ if (ctx->API == API_OPENGLES2 || prog->IsES)
+ linker_error(prog, "shader uses too many output vectors "
+ "(%u > %u)\n",
+ output_vectors,
+ max_output_components / 4);
+ else
+ linker_error(prog, "shader uses too many output components "
+ "(%u > %u)\n",
+ output_components,
+ max_output_components);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool
+check_against_input_limit(struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ gl_shader *consumer)
{
- unsigned varying_vectors = 0;
+ unsigned input_vectors = 0;
foreach_list(node, consumer->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if (var && var->mode == ir_var_shader_in &&
+ if (var && var->data.mode == ir_var_shader_in &&
is_varying_var(consumer->Type, var)) {
- /* The packing rules used for vertex shader inputs are also
- * used for fragment shader inputs.
- */
- varying_vectors += var->type->count_attribute_slots();
+ input_vectors += var->type->count_attribute_slots();
}
}
- if (ctx->API == API_OPENGLES2 || prog->IsES) {
- if (varying_vectors > ctx->Const.MaxVarying) {
- linker_error(prog, "shader uses too many varying vectors "
+ unsigned max_input_components;
+ switch (consumer->Type) {
+ case GL_GEOMETRY_SHADER:
+ max_input_components = ctx->Const.GeometryProgram.MaxInputComponents;
+ break;
+ case GL_FRAGMENT_SHADER:
+ max_input_components = ctx->Const.FragmentProgram.MaxInputComponents;
+ break;
+ case GL_VERTEX_SHADER:
+ default:
+ assert(!"Should not get here.");
+ return false;
+ }
+
+ const unsigned input_components = input_vectors * 4;
+ if (input_components > max_input_components) {
+ if (ctx->API == API_OPENGLES2 || prog->IsES)
+ linker_error(prog, "shader uses too many input vectors "
"(%u > %u)\n",
- varying_vectors, ctx->Const.MaxVarying);
- return false;
- }
- } else {
- const unsigned float_components = varying_vectors * 4;
- if (float_components > ctx->Const.MaxVarying * 4) {
- linker_error(prog, "shader uses too many varying components "
+ input_vectors,
+ max_input_components / 4);
+ else
+ linker_error(prog, "shader uses too many input components "
"(%u > %u)\n",
- float_components, ctx->Const.MaxVarying * 4);
- return false;
- }
+ input_components,
+ max_input_components);
+
+ return false;
}
return true;