static nir_register * get_reg_for_deref(nir_deref_var *deref, struct locals_to_regs_state *state) { uint32_t hash = hash_deref(deref); struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(state->regs_table, hash, deref); if (entry) return entry->data; unsigned array_size = 1; nir_deref *tail = &deref->deref; while (tail->child) { if (tail->child->deref_type == nir_deref_type_array) array_size *= glsl_get_length(tail->type); tail = tail->child; } assert(glsl_type_is_vector(tail->type) || glsl_type_is_scalar(tail->type)); nir_register *reg = nir_local_reg_create(state->impl); reg->num_components = glsl_get_vector_elements(tail->type); reg->num_array_elems = array_size > 1 ? array_size : 0; reg->bit_size = glsl_get_bit_size(glsl_get_base_type(tail->type)); _mesa_hash_table_insert_pre_hashed(state->regs_table, hash, deref, reg); nir_array_add(&state->derefs_array, nir_deref_var *, deref); return reg; }
static nir_register * 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); struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(state->regs_table, hash, deref); if (entry) return entry->data; unsigned array_size = 1; for (nir_deref_instr *d = deref; d; d = nir_deref_instr_parent(d)) { if (d->deref_type == nir_deref_type_array) array_size *= glsl_get_length(nir_deref_instr_parent(d)->type); } assert(glsl_type_is_vector_or_scalar(deref->type)); nir_register *reg = nir_local_reg_create(state->builder.impl); reg->num_components = glsl_get_vector_elements(deref->type); reg->num_array_elems = array_size > 1 ? array_size : 0; reg->bit_size = glsl_get_bit_size(deref->type); _mesa_hash_table_insert_pre_hashed(state->regs_table, hash, deref, reg); return reg; }
void glsl_get_natural_size_align_bytes(const struct glsl_type *type, unsigned *size, unsigned *align) { switch (type->base_type) { case GLSL_TYPE_UINT8: case GLSL_TYPE_INT8: case GLSL_TYPE_UINT16: case GLSL_TYPE_INT16: case GLSL_TYPE_FLOAT16: case GLSL_TYPE_UINT: case GLSL_TYPE_INT: case GLSL_TYPE_FLOAT: case GLSL_TYPE_BOOL: case GLSL_TYPE_DOUBLE: case GLSL_TYPE_UINT64: case GLSL_TYPE_INT64: { unsigned N = glsl_get_bit_size(type) / 8; *size = N * type->components(); *align = N; break; } case GLSL_TYPE_ARRAY: { unsigned elem_size, elem_align; glsl_get_natural_size_align_bytes(type->fields.array, &elem_size, &elem_align); *align = elem_align; *size = type->length * ALIGN_POT(elem_size, elem_align); break; } case GLSL_TYPE_STRUCT: *size = 0; *align = 0; for (unsigned i = 0; i < type->length; i++) { unsigned elem_size, elem_align; glsl_get_natural_size_align_bytes(type->fields.structure[i].type, &elem_size, &elem_align); *align = MAX2(*align, elem_align); *size = ALIGN_POT(*size, elem_align) + elem_size; } break; case GLSL_TYPE_SAMPLER: case GLSL_TYPE_ATOMIC_UINT: case GLSL_TYPE_SUBROUTINE: case GLSL_TYPE_IMAGE: case GLSL_TYPE_VOID: case GLSL_TYPE_ERROR: case GLSL_TYPE_INTERFACE: case GLSL_TYPE_FUNCTION: unreachable("type does not have a natural size"); } }
static void handle_glsl450_interpolation(struct vtn_builder *b, enum GLSLstd450 opcode, const uint32_t *w, unsigned count) { const struct glsl_type *dest_type = vtn_value(b, w[1], vtn_value_type_type)->type->type; struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa); val->ssa = vtn_create_ssa_value(b, dest_type); nir_intrinsic_op op; switch (opcode) { case GLSLstd450InterpolateAtCentroid: op = nir_intrinsic_interp_var_at_centroid; break; case GLSLstd450InterpolateAtSample: op = nir_intrinsic_interp_var_at_sample; break; case GLSLstd450InterpolateAtOffset: op = nir_intrinsic_interp_var_at_offset; break; default: unreachable("Invalid opcode"); } nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->nb.shader, op); nir_deref_var *deref = vtn_nir_deref(b, w[5]); intrin->variables[0] = nir_deref_as_var(nir_copy_deref(intrin, &deref->deref)); switch (opcode) { case GLSLstd450InterpolateAtCentroid: break; case GLSLstd450InterpolateAtSample: case GLSLstd450InterpolateAtOffset: intrin->src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[6])->def); break; default: unreachable("Invalid opcode"); } intrin->num_components = glsl_get_vector_elements(dest_type); nir_ssa_dest_init(&intrin->instr, &intrin->dest, glsl_get_vector_elements(dest_type), glsl_get_bit_size(dest_type), NULL); val->ssa->def = &intrin->dest.ssa; nir_builder_instr_insert(&b->nb, &intrin->instr); }
static void _vtn_load_store_tail(struct vtn_builder *b, nir_intrinsic_op op, bool load, nir_ssa_def *index, nir_ssa_def *offset, struct vtn_ssa_value **inout, const struct glsl_type *type) { nir_intrinsic_instr *instr = nir_intrinsic_instr_create(b->nb.shader, op); instr->num_components = glsl_get_vector_elements(type); int src = 0; if (!load) { nir_intrinsic_set_write_mask(instr, (1 << instr->num_components) - 1); instr->src[src++] = nir_src_for_ssa((*inout)->def); } /* We set the base and size for push constant load to the entire push * constant block for now. */ if (op == nir_intrinsic_load_push_constant) { nir_intrinsic_set_base(instr, 0); nir_intrinsic_set_range(instr, 128); } if (index) instr->src[src++] = nir_src_for_ssa(index); instr->src[src++] = nir_src_for_ssa(offset); if (load) { nir_ssa_dest_init(&instr->instr, &instr->dest, instr->num_components, glsl_get_bit_size(glsl_get_base_type(type)), NULL); (*inout)->def = &instr->dest.ssa; } nir_builder_instr_insert(&b->nb, &instr->instr); if (load && glsl_get_base_type(type) == GLSL_TYPE_BOOL) (*inout)->def = nir_ine(&b->nb, (*inout)->def, nir_imm_int(&b->nb, 0)); }
static void validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) { unsigned bit_size = 0; if (instr->intrinsic == nir_intrinsic_load_var || instr->intrinsic == nir_intrinsic_store_var) { const struct glsl_type *type = nir_deref_tail(&instr->variables[0]->deref)->type; bit_size = glsl_get_bit_size(type); } unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs; for (unsigned i = 0; i < num_srcs; i++) { unsigned components_read = nir_intrinsic_infos[instr->intrinsic].src_components[i]; if (components_read == 0) components_read = instr->num_components; validate_assert(state, components_read > 0); validate_src(&instr->src[i], state, bit_size, components_read); } unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables; for (unsigned i = 0; i < num_vars; i++) { validate_deref_var(instr, instr->variables[i], state); } if (nir_intrinsic_infos[instr->intrinsic].has_dest) { unsigned components_written = nir_intrinsic_infos[instr->intrinsic].dest_components; if (components_written == 0) components_written = instr->num_components; validate_assert(state, components_written > 0); validate_dest(&instr->dest, state, bit_size, components_written); } switch (instr->intrinsic) { case nir_intrinsic_load_var: { const struct glsl_type *type = nir_deref_tail(&instr->variables[0]->deref)->type; validate_assert(state, glsl_type_is_vector_or_scalar(type) || (instr->variables[0]->var->data.mode == nir_var_uniform && glsl_get_base_type(type) == GLSL_TYPE_SUBROUTINE)); validate_assert(state, instr->num_components == glsl_get_vector_elements(type)); break; } case nir_intrinsic_store_var: { const struct glsl_type *type = nir_deref_tail(&instr->variables[0]->deref)->type; validate_assert(state, glsl_type_is_vector_or_scalar(type) || (instr->variables[0]->var->data.mode == nir_var_uniform && glsl_get_base_type(type) == GLSL_TYPE_SUBROUTINE)); validate_assert(state, instr->num_components == glsl_get_vector_elements(type)); validate_assert(state, instr->variables[0]->var->data.mode != nir_var_shader_in && instr->variables[0]->var->data.mode != nir_var_uniform && instr->variables[0]->var->data.mode != nir_var_shader_storage); validate_assert(state, (nir_intrinsic_write_mask(instr) & ~((1 << instr->num_components) - 1)) == 0); break; } case nir_intrinsic_copy_var: validate_assert(state, nir_deref_tail(&instr->variables[0]->deref)->type == nir_deref_tail(&instr->variables[1]->deref)->type); validate_assert(state, instr->variables[0]->var->data.mode != nir_var_shader_in && instr->variables[0]->var->data.mode != nir_var_uniform && instr->variables[0]->var->data.mode != nir_var_shader_storage); break; default: break; } }
static void _vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_var *deref, nir_deref *tail, struct vtn_ssa_value *inout) { /* The deref tail may contain a deref to select a component of a vector (in * other words, it might not be an actual tail) so we have to save it away * here since we overwrite it later. */ nir_deref *old_child = tail->child; if (glsl_type_is_vector_or_scalar(tail->type)) { /* Terminate the deref chain in case there is one more link to pick * off a component of the vector. */ tail->child = NULL; nir_intrinsic_op op = load ? nir_intrinsic_load_var : nir_intrinsic_store_var; nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op); intrin->variables[0] = nir_deref_as_var(nir_copy_deref(intrin, &deref->deref)); intrin->num_components = glsl_get_vector_elements(tail->type); if (load) { nir_ssa_dest_init(&intrin->instr, &intrin->dest, intrin->num_components, glsl_get_bit_size(glsl_get_base_type(tail->type)), NULL); inout->def = &intrin->dest.ssa; } else { nir_intrinsic_set_write_mask(intrin, (1 << intrin->num_components) - 1); intrin->src[0] = nir_src_for_ssa(inout->def); } nir_builder_instr_insert(&b->nb, &intrin->instr); } else if (glsl_get_base_type(tail->type) == GLSL_TYPE_ARRAY || glsl_type_is_matrix(tail->type)) { unsigned elems = glsl_get_length(tail->type); nir_deref_array *deref_arr = nir_deref_array_create(b); deref_arr->deref_array_type = nir_deref_array_type_direct; deref_arr->deref.type = glsl_get_array_element(tail->type); tail->child = &deref_arr->deref; for (unsigned i = 0; i < elems; i++) { deref_arr->base_offset = i; _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]); } } else { assert(glsl_get_base_type(tail->type) == GLSL_TYPE_STRUCT); unsigned elems = glsl_get_length(tail->type); nir_deref_struct *deref_struct = nir_deref_struct_create(b, 0); tail->child = &deref_struct->deref; for (unsigned i = 0; i < elems; i++) { deref_struct->index = i; deref_struct->deref.type = glsl_get_struct_field(tail->type, i); _vtn_local_load_store(b, load, deref, tail->child, inout->elems[i]); } } tail->child = old_child; }