ir_variable *const var = ir->lhs->variable_referenced();
if (strcmp(name, var->name) == 0) {
- found = true;
- return visit_stop;
+ found = true;
+ return visit_stop;
}
return visit_continue_with_parent;
{
foreach_two_lists(formal_node, &ir->callee->parameters,
actual_node, &ir->actual_parameters) {
- ir_rvalue *param_rval = (ir_rvalue *) actual_node;
- ir_variable *sig_param = (ir_variable *) formal_node;
-
- if (sig_param->data.mode == ir_var_function_out ||
- sig_param->data.mode == ir_var_function_inout) {
- ir_variable *var = param_rval->variable_referenced();
- if (var && strcmp(name, var->name) == 0) {
- found = true;
- return visit_stop;
- }
- }
+ ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+ ir_variable *sig_param = (ir_variable *) formal_node;
+
+ if (sig_param->data.mode == ir_var_function_out ||
+ sig_param->data.mode == ir_var_function_inout) {
+ ir_variable *var = param_rval->variable_referenced();
+ if (var && strcmp(name, var->name) == 0) {
+ found = true;
+ return visit_stop;
+ }
+ }
}
if (ir->return_deref != NULL) {
- ir_variable *const var = ir->return_deref->variable_referenced();
+ ir_variable *const var = ir->return_deref->variable_referenced();
- if (strcmp(name, var->name) == 0) {
- found = true;
- return visit_stop;
- }
+ if (strcmp(name, var->name) == 0) {
+ found = true;
+ return visit_stop;
+ }
}
return visit_continue_with_parent;
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
if (strcmp(this->name, ir->var->name) == 0) {
- this->found = true;
- return visit_stop;
+ this->found = true;
+ return visit_stop;
}
return visit_continue;
linker_error(prog,
"vertex shader does not write to `gl_Position'. \n");
}
- return;
+ return;
}
}
if (frag_color.variable_found() && frag_data.variable_found()) {
linker_error(prog, "fragment shader writes to both "
- "`gl_FragColor' and `gl_FragData'\n");
+ "`gl_FragColor' and `gl_FragData'\n");
}
}
bool
validate_intrastage_arrays(struct gl_shader_program *prog,
ir_variable *const var,
- ir_variable *const existing)
+ ir_variable *const existing)
{
/* Consider the types to be "the same" if both types are arrays
* of the same type and one of the arrays is implicitly sized.
glsl_symbol_table variables;
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
- continue;
+ continue;
cross_validate_globals(prog, prog->_LinkedShaders[i]->ir, &variables,
true);
InterfaceBlockStageIndex[i][j] = -1;
if (sh == NULL)
- continue;
+ continue;
unsigned sh_num_blocks;
struct gl_uniform_block **sh_blks;
for (unsigned j = 0; j < *num_blks; j++) {
int stage_index = InterfaceBlockStageIndex[i][j];
- if (stage_index != -1) {
- struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+ if (stage_index != -1) {
+ struct gl_linked_shader *sh = prog->_LinkedShaders[i];
blks[j].stageref |= (1 << i);
sh->ShaderStorageBlocks : sh->UniformBlocks;
sh_blks[stage_index] = &blks[j];
- }
+ }
}
}
ir_function *func;
if ((func = inst->as_function()) != NULL) {
- sh->symbols->add_function(func);
+ sh->symbols->add_function(func);
} else if ((var = inst->as_variable()) != NULL) {
if (var->data.mode != ir_var_temporary)
sh->symbols->add_variable(var);
*/
void
remap_variables(ir_instruction *inst, struct gl_linked_shader *target,
- hash_table *temps)
+ hash_table *temps)
{
class remap_visitor : public ir_hierarchical_visitor {
public:
- remap_visitor(struct gl_linked_shader *target,
- hash_table *temps)
+ remap_visitor(struct gl_linked_shader *target, hash_table *temps)
{
- this->target = target;
- this->symbols = target->symbols;
- this->instructions = target->ir;
- this->temps = temps;
+ this->target = target;
+ this->symbols = target->symbols;
+ this->instructions = target->ir;
+ this->temps = temps;
}
virtual ir_visitor_status visit(ir_dereference_variable *ir)
{
- if (ir->var->data.mode == ir_var_temporary) {
- hash_entry *entry = _mesa_hash_table_search(temps, ir->var);
- ir_variable *var = entry ? (ir_variable *) entry->data : NULL;
-
- assert(var != NULL);
- ir->var = var;
- return visit_continue;
- }
-
- ir_variable *const existing =
- this->symbols->get_variable(ir->var->name);
- if (existing != NULL)
- ir->var = existing;
- else {
- ir_variable *copy = ir->var->clone(this->target, NULL);
-
- this->symbols->add_variable(copy);
- this->instructions->push_head(copy);
- ir->var = copy;
- }
-
- return visit_continue;
+ if (ir->var->data.mode == ir_var_temporary) {
+ hash_entry *entry = _mesa_hash_table_search(temps, ir->var);
+ ir_variable *var = entry ? (ir_variable *) entry->data : NULL;
+
+ assert(var != NULL);
+ ir->var = var;
+ return visit_continue;
+ }
+
+ ir_variable *const existing =
+ this->symbols->get_variable(ir->var->name);
+ if (existing != NULL)
+ ir->var = existing;
+ else {
+ ir_variable *copy = ir->var->clone(this->target, NULL);
+
+ this->symbols->add_variable(copy);
+ this->instructions->push_head(copy);
+ ir->var = copy;
+ }
+
+ return visit_continue;
}
private:
*/
exec_node *
move_non_declarations(exec_list *instructions, exec_node *last,
- bool make_copies, gl_linked_shader *target)
+ bool make_copies, gl_linked_shader *target)
{
hash_table *temps = NULL;
foreach_in_list_safe(ir_instruction, inst, instructions) {
if (inst->as_function())
- continue;
+ continue;
ir_variable *var = inst->as_variable();
if ((var != NULL) && (var->data.mode != ir_var_temporary))
- continue;
+ continue;
assert(inst->as_assignment()
|| inst->as_call()
|| inst->as_if() /* for initializers with the ?: operator */
- || ((var != NULL) && (var->data.mode == ir_var_temporary)));
+ || ((var != NULL) && (var->data.mode == ir_var_temporary)));
if (make_copies) {
- inst = inst->clone(target, NULL);
+ inst = inst->clone(target, NULL);
- if (var != NULL)
- _mesa_hash_table_insert(temps, var, inst);
- else
- remap_variables(inst, target, temps);
+ if (var != NULL)
+ _mesa_hash_table_insert(temps, var, inst);
+ else
+ remap_variables(inst, target, temps);
} else {
- inst->remove();
+ inst->remove();
}
last->insert_after(inst);
static void
link_xfb_stride_layout_qualifiers(struct gl_context *ctx,
struct gl_shader_program *prog,
- struct gl_linked_shader *linked_shader,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_linked_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
linked_shader->info.TransformFeedback.BufferStride[i] = 0;
for (unsigned j = 0; j < MAX_FEEDBACK_BUFFERS; j++) {
if (shader->info.TransformFeedback.BufferStride[j]) {
- if (linked_shader->info.TransformFeedback.BufferStride[j] != 0 &&
+ if (linked_shader->info.TransformFeedback.BufferStride[j] != 0 &&
shader->info.TransformFeedback.BufferStride[j] != 0 &&
- linked_shader->info.TransformFeedback.BufferStride[j] !=
+ linked_shader->info.TransformFeedback.BufferStride[j] !=
shader->info.TransformFeedback.BufferStride[j]) {
- linker_error(prog,
+ linker_error(prog,
"intrastage shaders defined with conflicting "
"xfb_stride for buffer %d (%d and %d)\n", j,
linked_shader->
info.TransformFeedback.BufferStride[j],
- shader->info.TransformFeedback.BufferStride[j]);
- return;
- }
+ shader->info.TransformFeedback.BufferStride[j]);
+ return;
+ }
if (shader->info.TransformFeedback.BufferStride[j])
- linked_shader->info.TransformFeedback.BufferStride[j] =
+ linked_shader->info.TransformFeedback.BufferStride[j] =
shader->info.TransformFeedback.BufferStride[j];
}
}
*/
static void
link_tcs_out_layout_qualifiers(struct gl_shader_program *prog,
- struct gl_linked_shader *linked_shader,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_linked_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
linked_shader->info.TessCtrl.VerticesOut = 0;
struct gl_shader *shader = shader_list[i];
if (shader->info.TessCtrl.VerticesOut != 0) {
- if (linked_shader->info.TessCtrl.VerticesOut != 0 &&
- linked_shader->info.TessCtrl.VerticesOut !=
+ if (linked_shader->info.TessCtrl.VerticesOut != 0 &&
+ linked_shader->info.TessCtrl.VerticesOut !=
shader->info.TessCtrl.VerticesOut) {
- linker_error(prog, "tessellation control shader defined with "
- "conflicting output vertex count (%d and %d)\n",
- linked_shader->info.TessCtrl.VerticesOut,
- shader->info.TessCtrl.VerticesOut);
- return;
- }
- linked_shader->info.TessCtrl.VerticesOut =
+ linker_error(prog, "tessellation control shader defined with "
+ "conflicting output vertex count (%d and %d)\n",
+ linked_shader->info.TessCtrl.VerticesOut,
+ shader->info.TessCtrl.VerticesOut);
+ return;
+ }
+ linked_shader->info.TessCtrl.VerticesOut =
shader->info.TessCtrl.VerticesOut;
}
}
*/
if (linked_shader->info.TessCtrl.VerticesOut == 0) {
linker_error(prog, "tessellation control shader didn't declare "
- "vertices out layout qualifier\n");
+ "vertices out layout qualifier\n");
return;
}
}
*/
static void
link_tes_in_layout_qualifiers(struct gl_shader_program *prog,
- struct gl_linked_shader *linked_shader,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_linked_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
linked_shader->info.TessEval.PrimitiveMode = PRIM_UNKNOWN;
linked_shader->info.TessEval.Spacing = 0;
struct gl_shader *shader = shader_list[i];
if (shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN) {
- if (linked_shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN &&
- linked_shader->info.TessEval.PrimitiveMode !=
+ if (linked_shader->info.TessEval.PrimitiveMode != PRIM_UNKNOWN &&
+ linked_shader->info.TessEval.PrimitiveMode !=
shader->info.TessEval.PrimitiveMode) {
- linker_error(prog, "tessellation evaluation shader defined with "
- "conflicting input primitive modes.\n");
- return;
- }
- linked_shader->info.TessEval.PrimitiveMode = shader->info.TessEval.PrimitiveMode;
+ linker_error(prog, "tessellation evaluation shader defined with "
+ "conflicting input primitive modes.\n");
+ return;
+ }
+ linked_shader->info.TessEval.PrimitiveMode = shader->info.TessEval.PrimitiveMode;
}
if (shader->info.TessEval.Spacing != 0) {
- if (linked_shader->info.TessEval.Spacing != 0 &&
- linked_shader->info.TessEval.Spacing !=
+ if (linked_shader->info.TessEval.Spacing != 0 &&
+ linked_shader->info.TessEval.Spacing !=
shader->info.TessEval.Spacing) {
- linker_error(prog, "tessellation evaluation shader defined with "
- "conflicting vertex spacing.\n");
- return;
- }
- linked_shader->info.TessEval.Spacing = shader->info.TessEval.Spacing;
+ linker_error(prog, "tessellation evaluation shader defined with "
+ "conflicting vertex spacing.\n");
+ return;
+ }
+ linked_shader->info.TessEval.Spacing = shader->info.TessEval.Spacing;
}
if (shader->info.TessEval.VertexOrder != 0) {
- if (linked_shader->info.TessEval.VertexOrder != 0 &&
- linked_shader->info.TessEval.VertexOrder !=
+ if (linked_shader->info.TessEval.VertexOrder != 0 &&
+ linked_shader->info.TessEval.VertexOrder !=
shader->info.TessEval.VertexOrder) {
- linker_error(prog, "tessellation evaluation shader defined with "
- "conflicting ordering.\n");
- return;
- }
- linked_shader->info.TessEval.VertexOrder =
+ linker_error(prog, "tessellation evaluation shader defined with "
+ "conflicting ordering.\n");
+ return;
+ }
+ linked_shader->info.TessEval.VertexOrder =
shader->info.TessEval.VertexOrder;
}
if (shader->info.TessEval.PointMode != -1) {
- if (linked_shader->info.TessEval.PointMode != -1 &&
- linked_shader->info.TessEval.PointMode !=
+ if (linked_shader->info.TessEval.PointMode != -1 &&
+ linked_shader->info.TessEval.PointMode !=
shader->info.TessEval.PointMode) {
- linker_error(prog, "tessellation evaluation shader defined with "
- "conflicting point modes.\n");
- return;
- }
- linked_shader->info.TessEval.PointMode =
+ linker_error(prog, "tessellation evaluation shader defined with "
+ "conflicting point modes.\n");
+ return;
+ }
+ linked_shader->info.TessEval.PointMode =
shader->info.TessEval.PointMode;
}
*/
if (linked_shader->info.TessEval.PrimitiveMode == PRIM_UNKNOWN) {
linker_error(prog,
- "tessellation evaluation shader didn't declare input "
- "primitive modes.\n");
+ "tessellation evaluation shader didn't declare input "
+ "primitive modes.\n");
return;
}
*/
static void
link_fs_inout_layout_qualifiers(struct gl_shader_program *prog,
- struct gl_linked_shader *linked_shader,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_linked_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
linked_shader->info.redeclares_gl_fragcoord = false;
linked_shader->info.uses_gl_fragcoord = false;
*/
static void
link_gs_inout_layout_qualifiers(struct gl_shader_program *prog,
- struct gl_linked_shader *linked_shader,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_linked_shader *linked_shader,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
linked_shader->info.Geom.VerticesOut = -1;
linked_shader->info.Geom.Invocations = 0;
struct gl_shader *shader = shader_list[i];
if (shader->info.Geom.InputType != PRIM_UNKNOWN) {
- if (linked_shader->info.Geom.InputType != PRIM_UNKNOWN &&
- linked_shader->info.Geom.InputType !=
+ if (linked_shader->info.Geom.InputType != PRIM_UNKNOWN &&
+ linked_shader->info.Geom.InputType !=
shader->info.Geom.InputType) {
- linker_error(prog, "geometry shader defined with conflicting "
- "input types\n");
- return;
- }
- linked_shader->info.Geom.InputType = shader->info.Geom.InputType;
+ linker_error(prog, "geometry shader defined with conflicting "
+ "input types\n");
+ return;
+ }
+ linked_shader->info.Geom.InputType = shader->info.Geom.InputType;
}
if (shader->info.Geom.OutputType != PRIM_UNKNOWN) {
- if (linked_shader->info.Geom.OutputType != PRIM_UNKNOWN &&
- linked_shader->info.Geom.OutputType !=
+ if (linked_shader->info.Geom.OutputType != PRIM_UNKNOWN &&
+ linked_shader->info.Geom.OutputType !=
shader->info.Geom.OutputType) {
- linker_error(prog, "geometry shader defined with conflicting "
- "output types\n");
- return;
- }
- linked_shader->info.Geom.OutputType = shader->info.Geom.OutputType;
+ linker_error(prog, "geometry shader defined with conflicting "
+ "output types\n");
+ return;
+ }
+ linked_shader->info.Geom.OutputType = shader->info.Geom.OutputType;
}
if (shader->info.Geom.VerticesOut != -1) {
- if (linked_shader->info.Geom.VerticesOut != -1 &&
- linked_shader->info.Geom.VerticesOut !=
+ if (linked_shader->info.Geom.VerticesOut != -1 &&
+ linked_shader->info.Geom.VerticesOut !=
shader->info.Geom.VerticesOut) {
- linker_error(prog, "geometry shader defined with conflicting "
- "output vertex count (%d and %d)\n",
- linked_shader->info.Geom.VerticesOut,
- shader->info.Geom.VerticesOut);
- return;
- }
- linked_shader->info.Geom.VerticesOut = shader->info.Geom.VerticesOut;
+ linker_error(prog, "geometry shader defined with conflicting "
+ "output vertex count (%d and %d)\n",
+ linked_shader->info.Geom.VerticesOut,
+ shader->info.Geom.VerticesOut);
+ return;
+ }
+ linked_shader->info.Geom.VerticesOut = shader->info.Geom.VerticesOut;
}
if (shader->info.Geom.Invocations != 0) {
- if (linked_shader->info.Geom.Invocations != 0 &&
- linked_shader->info.Geom.Invocations !=
+ if (linked_shader->info.Geom.Invocations != 0 &&
+ linked_shader->info.Geom.Invocations !=
shader->info.Geom.Invocations) {
- linker_error(prog, "geometry shader defined with conflicting "
- "invocation count (%d and %d)\n",
- linked_shader->info.Geom.Invocations,
- shader->info.Geom.Invocations);
- return;
- }
- linked_shader->info.Geom.Invocations = shader->info.Geom.Invocations;
+ linker_error(prog, "geometry shader defined with conflicting "
+ "invocation count (%d and %d)\n",
+ linked_shader->info.Geom.Invocations,
+ shader->info.Geom.Invocations);
+ return;
+ }
+ linked_shader->info.Geom.Invocations = shader->info.Geom.Invocations;
}
}
*/
if (linked_shader->info.Geom.InputType == PRIM_UNKNOWN) {
linker_error(prog,
- "geometry shader didn't declare primitive input type\n");
+ "geometry shader didn't declare primitive input type\n");
return;
}
if (linked_shader->info.Geom.OutputType == PRIM_UNKNOWN) {
linker_error(prog,
- "geometry shader didn't declare primitive output type\n");
+ "geometry shader didn't declare primitive output type\n");
return;
}
if (linked_shader->info.Geom.VerticesOut == -1) {
linker_error(prog,
- "geometry shader didn't declare max_vertices\n");
+ "geometry shader didn't declare max_vertices\n");
return;
}
*/
static struct gl_linked_shader *
link_intrastage_shaders(void *mem_ctx,
- struct gl_context *ctx,
- struct gl_shader_program *prog,
- struct gl_shader **shader_list,
- unsigned num_shaders)
+ struct gl_context *ctx,
+ struct gl_shader_program *prog,
+ struct gl_shader **shader_list,
+ unsigned num_shaders)
{
struct gl_uniform_block *ubo_blocks = NULL;
struct gl_uniform_block *ssbo_blocks = NULL;
glsl_symbol_table variables;
for (unsigned i = 0; i < num_shaders; i++) {
if (shader_list[i] == NULL)
- continue;
+ continue;
cross_validate_globals(prog, shader_list[i]->ir, &variables, false);
}
*/
for (unsigned i = 0; i < (num_shaders - 1); i++) {
foreach_in_list(ir_instruction, node, shader_list[i]->ir) {
- ir_function *const f = node->as_function();
-
- if (f == NULL)
- continue;
-
- for (unsigned j = i + 1; j < num_shaders; j++) {
- ir_function *const other =
- shader_list[j]->symbols->get_function(f->name);
-
- /* If the other shader has no function (and therefore no function
- * signatures) with the same name, skip to the next shader.
- */
- if (other == NULL)
- continue;
-
- foreach_in_list(ir_function_signature, sig, &f->signatures) {
- if (!sig->is_defined)
- continue;
-
- ir_function_signature *other_sig =
- other->exact_matching_signature(NULL, &sig->parameters);
-
- if (other_sig != NULL && other_sig->is_defined) {
- linker_error(prog, "function `%s' is multiply defined\n",
- f->name);
- return NULL;
- }
- }
- }
+ ir_function *const f = node->as_function();
+
+ if (f == NULL)
+ continue;
+
+ for (unsigned j = i + 1; j < num_shaders; j++) {
+ ir_function *const other =
+ shader_list[j]->symbols->get_function(f->name);
+
+ /* If the other shader has no function (and therefore no function
+ * signatures) with the same name, skip to the next shader.
+ */
+ if (other == NULL)
+ continue;
+
+ foreach_in_list(ir_function_signature, sig, &f->signatures) {
+ if (!sig->is_defined)
+ continue;
+
+ ir_function_signature *other_sig =
+ other->exact_matching_signature(NULL, &sig->parameters);
+
+ if (other_sig != NULL && other_sig->is_defined) {
+ linker_error(prog, "function `%s' is multiply defined\n",
+ f->name);
+ return NULL;
+ }
+ }
+ }
}
}
gl_shader *main = NULL;
for (unsigned i = 0; i < num_shaders; i++) {
if (_mesa_get_main_function_signature(shader_list[i]->symbols)) {
- main = shader_list[i];
- break;
+ main = shader_list[i];
+ break;
}
}
if (main == NULL) {
linker_error(prog, "%s shader lacks `main'\n",
- _mesa_shader_stage_to_string(shader_list[0]->Stage));
+ _mesa_shader_stage_to_string(shader_list[0]->Stage));
return NULL;
}
*/
exec_node *insertion_point =
move_non_declarations(linked->ir, (exec_node *) &main_sig->body, false,
- linked);
+ linked);
for (unsigned i = 0; i < num_shaders; i++) {
if (shader_list[i] == main)
- continue;
+ continue;
insertion_point = move_non_declarations(shader_list[i]->ir,
- insertion_point, true, linked);
+ insertion_point, true, linked);
}
if (!link_function_calls(prog, linked, shader_list, num_shaders)) {
update_array_sizes(struct gl_shader_program *prog)
{
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
- if (prog->_LinkedShaders[i] == NULL)
- continue;
+ if (prog->_LinkedShaders[i] == NULL)
+ continue;
foreach_in_list(ir_instruction, node, prog->_LinkedShaders[i]->ir) {
- ir_variable *const var = node->as_variable();
+ ir_variable *const var = node->as_variable();
- if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
- !var->type->is_array())
- continue;
+ if ((var == NULL) || (var->data.mode != ir_var_uniform) ||
+ !var->type->is_array())
+ continue;
- /* GL_ARB_uniform_buffer_object says that std140 uniforms
- * will not be eliminated. Since we always do std140, just
- * don't resize arrays in UBOs.
+ /* GL_ARB_uniform_buffer_object says that std140 uniforms
+ * will not be eliminated. Since we always do std140, just
+ * don't resize arrays in UBOs.
*
* Atomic counters are supposed to get deterministic
* locations assigned based on the declaration ordering and
* sizes, array compaction would mess that up.
*
* Subroutine uniforms are not removed.
- */
- if (var->is_in_buffer_block() || var->type->contains_atomic() ||
- var->type->contains_subroutine() || var->constant_initializer)
- continue;
-
- int size = var->data.max_array_access;
- for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
- if (prog->_LinkedShaders[j] == NULL)
- continue;
-
- foreach_in_list(ir_instruction, node2, prog->_LinkedShaders[j]->ir) {
- ir_variable *other_var = node2->as_variable();
- if (!other_var)
- continue;
-
- if (strcmp(var->name, other_var->name) == 0 &&
- other_var->data.max_array_access > size) {
- size = other_var->data.max_array_access;
- }
- }
- }
-
- if (size + 1 != (int)var->type->length) {
- /* If this is a built-in uniform (i.e., it's backed by some
- * fixed-function state), adjust the number of state slots to
- * match the new array size. The number of slots per array entry
- * is not known. It seems safe to assume that the total number of
- * slots is an integer multiple of the number of array elements.
- * Determine the number of slots per array element by dividing by
- * the old (total) size.
- */
+ */
+ if (var->is_in_buffer_block() || var->type->contains_atomic() ||
+ var->type->contains_subroutine() || var->constant_initializer)
+ continue;
+
+ int size = var->data.max_array_access;
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ if (prog->_LinkedShaders[j] == NULL)
+ continue;
+
+ foreach_in_list(ir_instruction, node2, prog->_LinkedShaders[j]->ir) {
+ ir_variable *other_var = node2->as_variable();
+ if (!other_var)
+ continue;
+
+ if (strcmp(var->name, other_var->name) == 0 &&
+ other_var->data.max_array_access > size) {
+ size = other_var->data.max_array_access;
+ }
+ }
+ }
+
+ if (size + 1 != (int)var->type->length) {
+ /* If this is a built-in uniform (i.e., it's backed by some
+ * fixed-function state), adjust the number of state slots to
+ * match the new array size. The number of slots per array entry
+ * is not known. It seems safe to assume that the total number of
+ * slots is an integer multiple of the number of array elements.
+ * Determine the number of slots per array element by dividing by
+ * the old (total) size.
+ */
const unsigned num_slots = var->get_num_state_slots();
- if (num_slots > 0) {
- var->set_num_state_slots((size + 1)
+ if (num_slots > 0) {
+ var->set_num_state_slots((size + 1)
* (num_slots / var->type->length));
- }
-
- var->type = glsl_type::get_array_instance(var->type->fields.array,
- size + 1);
- /* FINISHME: We should update the types of array
- * dereferences of this variable now.
- */
- }
+ }
+
+ var->type = glsl_type::get_array_instance(var->type->fields.array,
+ size + 1);
+ /* FINISHME: We should update the types of array
+ * dereferences of this variable now.
+ */
+ }
}
}
}
for (int i = 0; i <= max_bit_to_test; i++) {
if ((needed_mask & ~used_mask) == needed_mask)
- return i;
+ return i;
needed_mask <<= 1;
}
unsigned double_storage_locations = 0;
assert((target_index == MESA_SHADER_VERTEX)
- || (target_index == MESA_SHADER_FRAGMENT));
+ || (target_index == MESA_SHADER_FRAGMENT));
gl_linked_shader *const sh = prog->_LinkedShaders[target_index];
if (sh == NULL)
/* Used below in the call to qsort. */
static int compare(const void *a, const void *b)
{
- const temp_attr *const l = (const temp_attr *) a;
- const temp_attr *const r = (const temp_attr *) b;
+ const temp_attr *const l = (const temp_attr *) a;
+ const temp_attr *const r = (const temp_attr *) b;
- /* Reversed because we want a descending order sort below. */
- return r->slots - l->slots;
+ /* Reversed because we want a descending order sort below. */
+ return r->slots - l->slots;
}
} to_assign[32];
assert(max_index <= 32);
ir_variable *const var = node->as_variable();
if ((var == NULL) || (var->data.mode != (unsigned) direction))
- continue;
+ continue;
if (var->data.explicit_location) {
var->data.is_unmatched_generic_inout = 0;
- if ((var->data.location >= (int)(max_index + generic_base))
- || (var->data.location < 0)) {
- linker_error(prog,
- "invalid explicit location %d specified for `%s'\n",
- (var->data.location < 0)
- ? var->data.location
+ if ((var->data.location >= (int)(max_index + generic_base))
+ || (var->data.location < 0)) {
+ linker_error(prog,
+ "invalid explicit location %d specified for `%s'\n",
+ (var->data.location < 0)
+ ? var->data.location
: var->data.location - generic_base,
- var->name);
- return false;
- }
+ var->name);
+ return false;
+ }
} else if (target_index == MESA_SHADER_VERTEX) {
- unsigned binding;
+ unsigned binding;
- if (prog->AttributeBindings->get(binding, var->name)) {
- assert(binding >= VERT_ATTRIB_GENERIC0);
- var->data.location = binding;
+ if (prog->AttributeBindings->get(binding, var->name)) {
+ assert(binding >= VERT_ATTRIB_GENERIC0);
+ var->data.location = binding;
var->data.is_unmatched_generic_inout = 0;
- }
+ }
} else if (target_index == MESA_SHADER_FRAGMENT) {
- unsigned binding;
- unsigned index;
+ unsigned binding;
+ unsigned index;
const char *name = var->name;
const glsl_type *type = var->type;
* add it to the list of variables that need linker-assigned locations.
*/
if (var->data.location != -1) {
- if (var->data.location >= generic_base && var->data.index < 1) {
- /* From page 61 of the OpenGL 4.0 spec:
- *
- * "LinkProgram will fail if the attribute bindings assigned
- * by BindAttribLocation do not leave not enough space to
- * assign a location for an active matrix attribute or an
- * active attribute array, both of which require multiple
- * contiguous generic attributes."
- *
- * I think above text prohibits the aliasing of explicit and
- * automatic assignments. But, aliasing is allowed in manual
- * assignments of attribute locations. See below comments for
- * the details.
- *
- * From OpenGL 4.0 spec, page 61:
- *
- * "It is possible for an application to bind more than one
- * attribute name to the same location. This is referred to as
- * aliasing. This will only work if only one of the aliased
- * attributes is active in the executable program, or if no
- * path through the shader consumes more than one attribute of
- * a set of attributes aliased to the same location. A link
- * error can occur if the linker determines that every path
- * through the shader consumes multiple aliased attributes,
- * but implementations are not required to generate an error
- * in this case."
- *
- * From GLSL 4.30 spec, page 54:
- *
- * "A program will fail to link if any two non-vertex shader
- * input variables are assigned to the same location. For
- * vertex shaders, multiple input variables may be assigned
- * to the same location using either layout qualifiers or via
- * the OpenGL API. However, such aliasing is intended only to
- * support vertex shaders where each execution path accesses
- * at most one input per each location. Implementations are
- * permitted, but not required, to generate link-time errors
- * if they detect that every path through the vertex shader
- * executable accesses multiple inputs assigned to any single
- * location. For all shader types, a program will fail to link
- * if explicit location assignments leave the linker unable
- * to find space for other variables without explicit
- * assignments."
- *
- * From OpenGL ES 3.0 spec, page 56:
- *
- * "Binding more than one attribute name to the same location
- * is referred to as aliasing, and is not permitted in OpenGL
- * ES Shading Language 3.00 vertex shaders. LinkProgram will
- * fail when this condition exists. However, aliasing is
- * possible in OpenGL ES Shading Language 1.00 vertex shaders.
- * This will only work if only one of the aliased attributes
- * is active in the executable program, or if no path through
- * the shader consumes more than one attribute of a set of
- * attributes aliased to the same location. A link error can
- * occur if the linker determines that every path through the
- * shader consumes multiple aliased attributes, but implemen-
- * tations are not required to generate an error in this case."
- *
- * After looking at above references from OpenGL, OpenGL ES and
- * GLSL specifications, we allow aliasing of vertex input variables
- * in: OpenGL 2.0 (and above) and OpenGL ES 2.0.
- *
- * NOTE: This is not required by the spec but its worth mentioning
- * here that we're not doing anything to make sure that no path
- * through the vertex shader executable accesses multiple inputs
- * assigned to any single location.
- */
-
- /* Mask representing the contiguous slots that will be used by
- * this attribute.
- */
- const unsigned attr = var->data.location - generic_base;
- const unsigned use_mask = (1 << slots) - 1;
+ if (var->data.location >= generic_base && var->data.index < 1) {
+ /* From page 61 of the OpenGL 4.0 spec:
+ *
+ * "LinkProgram will fail if the attribute bindings assigned
+ * by BindAttribLocation do not leave not enough space to
+ * assign a location for an active matrix attribute or an
+ * active attribute array, both of which require multiple
+ * contiguous generic attributes."
+ *
+ * I think above text prohibits the aliasing of explicit and
+ * automatic assignments. But, aliasing is allowed in manual
+ * assignments of attribute locations. See below comments for
+ * the details.
+ *
+ * From OpenGL 4.0 spec, page 61:
+ *
+ * "It is possible for an application to bind more than one
+ * attribute name to the same location. This is referred to as
+ * aliasing. This will only work if only one of the aliased
+ * attributes is active in the executable program, or if no
+ * path through the shader consumes more than one attribute of
+ * a set of attributes aliased to the same location. A link
+ * error can occur if the linker determines that every path
+ * through the shader consumes multiple aliased attributes,
+ * but implementations are not required to generate an error
+ * in this case."
+ *
+ * From GLSL 4.30 spec, page 54:
+ *
+ * "A program will fail to link if any two non-vertex shader
+ * input variables are assigned to the same location. For
+ * vertex shaders, multiple input variables may be assigned
+ * to the same location using either layout qualifiers or via
+ * the OpenGL API. However, such aliasing is intended only to
+ * support vertex shaders where each execution path accesses
+ * at most one input per each location. Implementations are
+ * permitted, but not required, to generate link-time errors
+ * if they detect that every path through the vertex shader
+ * executable accesses multiple inputs assigned to any single
+ * location. For all shader types, a program will fail to link
+ * if explicit location assignments leave the linker unable
+ * to find space for other variables without explicit
+ * assignments."
+ *
+ * From OpenGL ES 3.0 spec, page 56:
+ *
+ * "Binding more than one attribute name to the same location
+ * is referred to as aliasing, and is not permitted in OpenGL
+ * ES Shading Language 3.00 vertex shaders. LinkProgram will
+ * fail when this condition exists. However, aliasing is
+ * possible in OpenGL ES Shading Language 1.00 vertex shaders.
+ * This will only work if only one of the aliased attributes
+ * is active in the executable program, or if no path through
+ * the shader consumes more than one attribute of a set of
+ * attributes aliased to the same location. A link error can
+ * occur if the linker determines that every path through the
+ * shader consumes multiple aliased attributes, but implemen-
+ * tations are not required to generate an error in this case."
+ *
+ * After looking at above references from OpenGL, OpenGL ES and
+ * GLSL specifications, we allow aliasing of vertex input variables
+ * in: OpenGL 2.0 (and above) and OpenGL ES 2.0.
+ *
+ * NOTE: This is not required by the spec but its worth mentioning
+ * here that we're not doing anything to make sure that no path
+ * through the vertex shader executable accesses multiple inputs
+ * assigned to any single location.
+ */
+
+ /* Mask representing the contiguous slots that will be used by
+ * this attribute.
+ */
+ const unsigned attr = var->data.location - generic_base;
+ const unsigned use_mask = (1 << slots) - 1;
const char *const string = (target_index == MESA_SHADER_VERTEX)
? "vertex shader input" : "fragment shader output";
return false;
}
- /* Generate a link error if the set of bits requested for this
- * attribute overlaps any previously allocated bits.
- */
- if ((~(use_mask << attr) & used_locations) != used_locations) {
+ /* Generate a link error if the set of bits requested for this
+ * attribute overlaps any previously allocated bits.
+ */
+ if ((~(use_mask << attr) & used_locations) != used_locations) {
if (target_index == MESA_SHADER_FRAGMENT && !prog->IsES) {
/* From section 4.4.2 (Output Layout Qualifiers) of the GLSL
* 4.40 spec:
for (unsigned i = 0; i < assigned_attr; i++) {
unsigned assigned_slots =
assigned[i]->type->count_attribute_slots(false);
- unsigned assig_attr =
+ unsigned assig_attr =
assigned[i]->data.location - generic_base;
- unsigned assigned_use_mask = (1 << assigned_slots) - 1;
+ unsigned assigned_use_mask = (1 << assigned_slots) - 1;
if ((assigned_use_mask << assig_attr) &
(use_mask << attr)) {
"to %s `%s' %d %d %d\n", string, var->name,
used_locations, use_mask, attr);
}
- }
+ }
- used_locations |= (use_mask << attr);
+ used_locations |= (use_mask << attr);
/* From the GL 4.5 core spec, section 11.1.1 (Vertex Attributes):
*
*/
if (var->type->without_array()->is_dual_slot())
double_storage_locations |= (use_mask << attr);
- }
+ }
assigned[assigned_attr] = var;
assigned_attr++;
- continue;
+ continue;
}
if (num_attr >= max_index) {
_mesa_bitcount(used_locations & ((1 << max_index) - 1)) +
_mesa_bitcount(double_storage_locations);
if (total_attribs_size > max_index) {
- linker_error(prog,
- "attempt to use %d vertex attribute slots only %d available ",
- total_attribs_size, max_index);
- return false;
+ linker_error(prog,
+ "attempt to use %d vertex attribute slots only %d available ",
+ total_attribs_size, max_index);
+ return false;
}
}
find_deref_visitor find("gl_Vertex");
find.run(sh->ir);
if (find.variable_found())
- used_locations |= (1 << 0);
+ used_locations |= (1 << 0);
}
for (unsigned i = 0; i < num_attr; i++) {
int location = find_available_slots(used_locations, to_assign[i].slots);
if (location < 0) {
- const char *const string = (target_index == MESA_SHADER_VERTEX)
- ? "vertex shader input" : "fragment shader output";
-
- linker_error(prog,
- "insufficient contiguous locations "
- "available for %s `%s'\n",
- string, to_assign[i].var->name);
- return false;
+ const char *const string = (target_index == MESA_SHADER_VERTEX)
+ ? "vertex shader input" : "fragment shader output";
+
+ linker_error(prog,
+ "insufficient contiguous locations "
+ "available for %s `%s'\n",
+ string, to_assign[i].var->name);
+ return false;
}
to_assign[i].var->data.location = generic_base + location;
_mesa_bitcount(used_locations & ((1 << max_index) - 1)) +
_mesa_bitcount(double_storage_locations);
if (total_attribs_size > max_index) {
- linker_error(prog,
- "attempt to use %d vertex attribute slots only %d available ",
- total_attribs_size, max_index);
- return false;
+ linker_error(prog,
+ "attempt to use %d vertex attribute slots only %d available ",
+ total_attribs_size, max_index);
+ return false;
}
}
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
if (sh == NULL)
- continue;
+ continue;
if (sh->num_samplers > ctx->Const.Program[i].MaxTextureImageUnits) {
- linker_error(prog, "Too many %s shader texture samplers\n",
- _mesa_shader_stage_to_string(i));
+ linker_error(prog, "Too many %s shader texture samplers\n",
+ _mesa_shader_stage_to_string(i));
}
if (sh->num_uniform_components >
linker_warning(prog, "Too many %s shader default uniform block "
"components, but the driver will try to optimize "
"them out; this is non-portable out-of-spec "
- "behavior\n",
+ "behavior\n",
_mesa_shader_stage_to_string(i));
} else {
linker_error(prog, "Too many %s shader default uniform block "
- "components\n",
+ "components\n",
_mesa_shader_stage_to_string(i));
}
}
if (sh->num_combined_uniform_components >
- ctx->Const.Program[i].MaxCombinedUniformComponents) {
+ ctx->Const.Program[i].MaxCombinedUniformComponents) {
if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) {
linker_warning(prog, "Too many %s shader uniform components, "
"but the driver will try to optimize them out; "
dynamic_sampler_array_indexing_visitor v;
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
- continue;
+ continue;
bool no_dynamic_indexing =
ctx->Const.ShaderCompilerOptions[i].EmitNoIndirectSampler;
if (!fn->num_subroutine_types)
continue;
- /* these should have been calculated earlier. */
- assert(fn->subroutine_index != -1);
+ /* these should have been calculated earlier. */
+ assert(fn->subroutine_index != -1);
if (sh->NumSubroutineFunctions + 1 > MAX_SUBROUTINES) {
linker_error(prog, "Too many subroutine functions declared.\n");
return;
max_version = MAX2(max_version, prog->Shaders[i]->Version);
if (prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) {
- linker_error(prog, "all shaders must use same shading "
- "language version\n");
- goto done;
+ linker_error(prog, "all shaders must use same shading "
+ "language version\n");
+ goto done;
}
if (prog->Shaders[i]->info.ARB_fragment_coord_conventions_enable) {
*/
if (prog->Shaders[0]->IsES && min_version != max_version) {
linker_error(prog, "all shaders must use same shading "
- "language version\n");
+ "language version\n");
goto done;
}
if (num_shaders[MESA_SHADER_GEOMETRY] > 0 &&
num_shaders[MESA_SHADER_VERTEX] == 0) {
linker_error(prog, "Geometry shader must be linked with "
- "vertex shader\n");
+ "vertex shader\n");
goto done;
}
if (num_shaders[MESA_SHADER_TESS_EVAL] > 0 &&
num_shaders[MESA_SHADER_VERTEX] == 0) {
linker_error(prog, "Tessellation evaluation shader must be linked "
- "with vertex shader\n");
+ "with vertex shader\n");
goto done;
}
if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
num_shaders[MESA_SHADER_VERTEX] == 0) {
linker_error(prog, "Tessellation control shader must be linked with "
- "vertex shader\n");
+ "vertex shader\n");
goto done;
}
if (num_shaders[MESA_SHADER_TESS_CTRL] > 0 &&
num_shaders[MESA_SHADER_TESS_EVAL] == 0) {
linker_error(prog, "Tessellation control shader must be linked with "
- "tessellation evaluation shader\n");
+ "tessellation evaluation shader\n");
goto done;
}
}
for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] != NULL) {
- _mesa_delete_linked_shader(ctx, prog->_LinkedShaders[i]);
+ _mesa_delete_linked_shader(ctx, prog->_LinkedShaders[i]);
}
prog->_LinkedShaders[i] = NULL;
if (max_version >= (prog->IsES ? 300 : 130)) {
struct gl_linked_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
if (sh) {
- lower_discard_flow(sh->ir);
+ lower_discard_flow(sh->ir);
}
}
*/
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
if (prog->_LinkedShaders[i] == NULL)
- continue;
+ continue;
detect_recursion_linked(prog, prog->_LinkedShaders[i]->ir);
if (!prog->LinkStatus)
- goto done;
+ goto done;
if (ctx->Const.ShaderCompilerOptions[i].LowerCombinedClipCullDistance) {
lower_clip_cull_distance(prog, prog->_LinkedShaders[i]);
while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false,
&ctx->Const.ShaderCompilerOptions[i],
ctx->Const.NativeIntegers))
- ;
+ ;
lower_const_arrays_to_uniforms(prog->_LinkedShaders[i]->ir, i);
propagate_invariance(prog->_LinkedShaders[i]->ir);
if (!prog->SeparateShader && ctx->API == API_OPENGLES2 &&
num_shaders[MESA_SHADER_COMPUTE] == 0) {
if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
- linker_error(prog, "program lacks a vertex shader\n");
+ linker_error(prog, "program lacks a vertex shader\n");
} else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
- linker_error(prog, "program lacks a fragment shader\n");
+ linker_error(prog, "program lacks a fragment shader\n");
}
}
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
free(shader_list[i]);
if (prog->_LinkedShaders[i] == NULL)
- continue;
+ continue;
/* Do a final validation step to make sure that the IR wasn't
* invalidated by any modifications performed after intrastage linking.