exec_list_make_empty(&shader->functions);
+ list_inithead(&shader->gc_list);
+
shader->num_inputs = 0;
shader->num_outputs = 0;
shader->num_uniforms = 0;
for (unsigned i = 0; i < num_srcs; i++)
alu_src_init(&instr->src[i]);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
dest_init(&instr->dest);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
instr->type = type;
instr->target = NULL;
instr->else_target = NULL;
+
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
nir_ssa_def_init(&instr->instr, &instr->def, num_components, bit_size);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
for (unsigned i = 0; i < num_srcs; i++)
src_init(&instr->src[i]);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
for (unsigned i = 0; i < num_params; i++)
src_init(&instr->params[i]);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
instr->sampler_index = 0;
memcpy(instr->tg4_offsets, default_tg4_offsets, sizeof(instr->tg4_offsets));
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
dest_init(&instr->dest);
exec_list_make_empty(&instr->srcs);
+
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
exec_list_make_empty(&instr->entries);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
nir_ssa_def_init(&instr->instr, &instr->def, num_components, bit_size);
+ list_add(&instr->instr.gc_node, &shader->gc_list);
+
return instr;
}
void nir_instr_free(nir_instr *instr)
{
+ list_del(&instr->gc_node);
ralloc_free(instr);
}
typedef struct nir_instr {
struct exec_node node;
+ struct list_head gc_node;
struct nir_block *block;
nir_instr_type type;
struct exec_list functions; /** < list of nir_function */
+ struct list_head gc_list; /** < list of all nir_instrs allocated on the shader but not yet freed. */
+
/**
* The size of the variable space for load_input_*, load_uniform_*, etc.
* intrinsics. This is in back-end specific units which is likely one of
/* We have to move all the linked lists over separately because we need the
* pointers in the list elements to point to the lists in dst and not src.
*/
+ list_replace(&src->gc_list, &dst->gc_list);
+ list_inithead(&src->gc_list);
exec_list_move_nodes_to(&src->variables, &dst->variables);
/* Now move the functions over. This takes a tiny bit more work */
block->live_out = NULL;
nir_foreach_instr(instr, block) {
+ list_del(&instr->gc_node);
+ list_add(&instr->gc_node, &nir->gc_list);
+
ralloc_steal(nir, instr);
nir_foreach_src(instr, sweep_src_indirect, nir);
{
void *rubbish = ralloc_context(NULL);
+ struct list_head instr_gc_list;
+ list_inithead(&instr_gc_list);
+
+ list_replace(&nir->gc_list, &instr_gc_list);
+ list_inithead(&nir->gc_list);
+
/* First, move ownership of all the memory to a temporary context; assume dead. */
ralloc_adopt(rubbish, nir);
sweep_function(nir, func);
}
+ /* Manually GCed instrs now before ralloc_free()ing the other rubbish, to
+ * ensure that the shader's GC list was maintained without ralloc_freeing any
+ * instrs behind our back. Note that the instr free routine will remove it
+ * from the list.
+ */
+ list_for_each_entry_safe(nir_instr, instr, &instr_gc_list, gc_node) {
+ nir_instr_free(instr);
+ }
+ assert(list_is_empty(&instr_gc_list));
+
ralloc_steal(nir, nir->constant_data);
/* Free everything we didn't steal back. */
/* map of instruction/var/etc to failed assert string */
struct hash_table *errors;
+
+ struct set *shader_gc_list;
} validate_state;
static void
state->instr = instr;
+ validate_assert(state, _mesa_set_search(state->shader_gc_list, instr));
+
switch (instr->type) {
case nir_instr_type_alu:
validate_alu_instr(nir_instr_as_alu(instr), state);
state->blocks = _mesa_pointer_set_create(state->mem_ctx);
state->var_defs = _mesa_pointer_hash_table_create(state->mem_ctx);
state->errors = _mesa_pointer_hash_table_create(state->mem_ctx);
+ state->shader_gc_list = _mesa_pointer_set_create(state->mem_ctx);
state->loop = NULL;
state->instr = NULL;
validate_state state;
init_validate_state(&state);
+ list_for_each_entry(nir_instr, instr, &shader->gc_list, gc_node) {
+ _mesa_set_add(state.shader_gc_list, instr);
+ }
+
state.shader = shader;
nir_variable_mode valid_modes =