compiler/nir: Add support for variable initialization from a pointer

Add a pointer_initializer field to nir_variable analogous to
constant_initializer, which can be used to initialize the nir_variable
to a pointer to another nir_variable. Just like the
constant_initializer, the pointer_initializer gets eliminated in the
nir_lower_constant_initializers pass.

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3047>
This commit is contained in:
Arcady Goldmints-Orlov 2019-12-10 15:37:53 -05:00 committed by Caio Marcelo de Oliveira Filho
parent 461c40e0fd
commit 7acc81056f
8 changed files with 41 additions and 11 deletions

View File

@ -578,6 +578,14 @@ typedef struct nir_variable {
*/
nir_constant *constant_initializer;
/**
* Global variable assigned in the initializer of the variable
* This field should only be used temporarily by creators of NIR shaders
* and then lower_constant_initializers can be used to get rid of them.
* Most of the rest of NIR ignores this field or asserts that it's NULL.
*/
struct nir_variable *pointer_initializer;
/**
* For variables that are in an interface block or are an instance of an
* interface block, this is the \c GLSL_TYPE_INTERFACE type for that block.

View File

@ -61,15 +61,23 @@ lower_const_initializer(struct nir_builder *b, struct exec_list *var_list)
b->cursor = nir_before_cf_list(&b->impl->body);
nir_foreach_variable(var, var_list) {
if (!var->constant_initializer)
continue;
if (var->constant_initializer) {
build_constant_load(b, nir_build_deref_var(b, var),
var->constant_initializer);
progress = true;
progress = true;
var->constant_initializer = NULL;
} else if (var->pointer_initializer) {
nir_deref_instr *src_deref = nir_build_deref_var(b, var->pointer_initializer);
nir_deref_instr *dst_deref = nir_build_deref_var(b, var);
build_constant_load(b, nir_build_deref_var(b, var),
var->constant_initializer);
/* Note that this stores a pointer to src into dst */
nir_store_deref(b, dst_deref, &src_deref->dest.ssa, ~0);
progress = true;
var->pointer_initializer = NULL;
}
var->constant_initializer = NULL;
}
return progress;

View File

@ -297,7 +297,7 @@ create_shadow_temp(struct lower_io_state *state, nir_variable *var)
/* Reparent the name to the new variable */
ralloc_steal(nvar, nvar->name);
assert(nvar->constant_initializer == NULL);
assert(nvar->constant_initializer == NULL && nvar->pointer_initializer == NULL);
/* Give the original a new name with @<mode>-temp appended */
const char *mode = (temp->data.mode == nir_var_shader_in) ? "in" : "out";

View File

@ -101,7 +101,8 @@ get_reg_for_deref(nir_deref_instr *deref, struct locals_to_regs_state *state)
{
uint32_t hash = hash_deref(deref);
assert(nir_deref_instr_get_variable(deref)->constant_initializer == NULL);
assert(nir_deref_instr_get_variable(deref)->constant_initializer == NULL &&
nir_deref_instr_get_variable(deref)->pointer_initializer == NULL);
struct hash_entry *entry =
_mesa_hash_table_search_pre_hashed(state->regs_table, hash, deref);

View File

@ -779,7 +779,8 @@ nir_lower_vars_to_ssa_impl(nir_function_impl *impl)
memset(store_blocks, 0,
BITSET_WORDS(state.impl->num_blocks) * sizeof(*store_blocks));
assert(node->path.path[0]->var->constant_initializer == NULL);
assert(node->path.path[0]->var->constant_initializer == NULL &&
node->path.path[0]->var->pointer_initializer == NULL);
if (node->stores) {
set_foreach(node->stores, store_entry) {

View File

@ -558,6 +558,8 @@ print_var_decl(nir_variable *var, print_state *state)
print_constant(var->constant_initializer, var->type, state);
fprintf(fp, " }");
}
if (var->pointer_initializer)
fprintf(fp, " = &%s", get_var_name(var->pointer_initializer, state));
fprintf(fp, "\n");
print_annotation(state, var);

View File

@ -206,12 +206,13 @@ union packed_var {
struct {
unsigned has_name:1;
unsigned has_constant_initializer:1;
unsigned has_pointer_initializer:1;
unsigned has_interface_type:1;
unsigned num_state_slots:7;
unsigned data_encoding:2;
unsigned type_same_as_last:1;
unsigned interface_type_same_as_last:1;
unsigned _pad:2;
unsigned _pad:1;
unsigned num_members:16;
} u;
};
@ -238,6 +239,7 @@ write_variable(write_ctx *ctx, const nir_variable *var)
flags.u.has_name = !ctx->strip && var->name;
flags.u.has_constant_initializer = !!(var->constant_initializer);
flags.u.has_pointer_initializer = !!(var->pointer_initializer);
flags.u.has_interface_type = !!(var->interface_type);
flags.u.type_same_as_last = var->type == ctx->last_type;
flags.u.interface_type_same_as_last =
@ -322,6 +324,8 @@ write_variable(write_ctx *ctx, const nir_variable *var)
}
if (var->constant_initializer)
write_constant(ctx, var->constant_initializer);
if (var->pointer_initializer)
write_lookup_object(ctx, var->pointer_initializer);
if (var->num_members > 0) {
blob_write_bytes(ctx->blob, (uint8_t *) var->members,
var->num_members * sizeof(*var->members));
@ -392,6 +396,12 @@ read_variable(read_ctx *ctx)
var->constant_initializer = read_constant(ctx, var);
else
var->constant_initializer = NULL;
if (flags.u.has_pointer_initializer)
var->pointer_initializer = read_object(ctx);
else
var->pointer_initializer = NULL;
var->num_members = flags.u.num_members;
if (var->num_members > 0) {
var->members = ralloc_array(var, struct nir_variable_data,

View File

@ -66,7 +66,7 @@ split_variable(struct nir_variable *var, nir_shader *shader,
assert(var->state_slots == NULL);
/* Constant initializers are currently not handled */
assert(var->constant_initializer == NULL);
assert(var->constant_initializer == NULL && var->pointer_initializer == NULL);
nir_variable **members =
ralloc_array(dead_ctx, nir_variable *, var->num_members);