var->data.max_array_access = ir->data.max_array_access;
var->num_state_slots = ir->get_num_state_slots();
- var->state_slots = ralloc_array(var, nir_state_slot, var->num_state_slots);
- ir_state_slot *state_slots = ir->get_state_slots();
- for (unsigned i = 0; i < var->num_state_slots; i++) {
- for (unsigned j = 0; j < 5; j++)
- var->state_slots[i].tokens[j] = state_slots[i].tokens[j];
- var->state_slots[i].swizzle = state_slots[i].swizzle;
+ if (var->num_state_slots > 0) {
+ var->state_slots = ralloc_array(var, nir_state_slot,
+ var->num_state_slots);
+
+ ir_state_slot *state_slots = ir->get_state_slots();
+ for (unsigned i = 0; i < var->num_state_slots; i++) {
+ for (unsigned j = 0; j < 5; j++)
+ var->state_slots[i].tokens[j] = state_slots[i].tokens[j];
+ var->state_slots[i].swizzle = state_slots[i].swizzle;
+ }
+ } else {
+ var->state_slots = NULL;
}
var->constant_value = constant_copy(ir->constant_value, var);
assert(0);
}
- nir_register *reg = nir_local_reg_create(impl);
- reg->num_components = 1;
-
nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
ir_dereference *param =
(ir_dereference *) ir->actual_parameters.get_head();
param->accept(this);
instr->variables[0] = this->deref_head;
- instr->dest.reg.reg = reg;
+ instr->dest.is_ssa = true;
+ nir_ssa_def_init(&instr->instr, &instr->dest.ssa, 1, NULL);
nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
nir_intrinsic_instr *store_instr =
- nir_intrinsic_instr_create(shader, nir_intrinsic_store_var_vec1);
+ nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
+ store_instr->num_components = 1;
ir->return_deref->accept(this);
store_instr->variables[0] = this->deref_head;
- store_instr->src[0].reg.reg = reg;
+ store_instr->src[0].is_ssa = true;
+ store_instr->src[0].ssa = &instr->dest.ssa;
nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr);
void
nir_visitor::visit(ir_assignment *ir)
{
- if (ir->write_mask != (1 << ir->lhs->type->vector_elements) - 1 &&
- ir->write_mask != 0) {
- /*
- * We have no good way to update only part of a variable, so just load
- * the LHS into a register, do a writemasked move, and then store it
- * back into the LHS. Copy propagation should get rid of the mess.
- */
-
- ir->lhs->accept(this);
- nir_deref_var *lhs_deref = this->deref_head;
- nir_register *reg = nir_local_reg_create(this->impl);
- reg->num_components = ir->lhs->type->vector_elements;
-
- nir_intrinsic_op op;
- switch (ir->lhs->type->vector_elements) {
- case 1: op = nir_intrinsic_load_var_vec1; break;
- case 2: op = nir_intrinsic_load_var_vec2; break;
- case 3: op = nir_intrinsic_load_var_vec3; break;
- case 4: op = nir_intrinsic_load_var_vec4; break;
- default: assert(0); break;
- }
-
- nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
- load->dest.reg.reg = reg;
- load->variables[0] = lhs_deref;
- nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
-
- nir_alu_instr *move =
- nir_alu_instr_create(this->shader,
- supports_ints ? nir_op_fmov : nir_op_imov);
- move->dest.dest.reg.reg = reg;
- move->dest.write_mask = ir->write_mask;
- move->src[0].src = evaluate_rvalue(ir->rhs);
-
- /*
- * GLSL IR will give us the input to the write-masked assignment in a
- * single packed vector, whereas we expect each input component to be in
- * the same channel as the writemask. So, for example, if the writemask
- * is xzw, then we have to swizzle x -> x, y -> z, and z -> w.
- */
-
- unsigned component = 0;
- for (unsigned i = 0; i < 4; i++) {
- if ((ir->write_mask >> i) & 1) {
- move->src[0].swizzle[i] = component++;
- } else {
- move->src[0].swizzle[i] = 0;
- }
- }
+ unsigned num_components = ir->lhs->type->vector_elements;
- if (ir->condition != NULL) {
- move->has_predicate = true;
- move->predicate = evaluate_rvalue(ir->condition);
- }
-
- nir_instr_insert_after_cf_list(this->cf_node_list, &move->instr);
-
- switch (ir->lhs->type->vector_elements) {
- case 1: op = nir_intrinsic_store_var_vec1; break;
- case 2: op = nir_intrinsic_store_var_vec2; break;
- case 3: op = nir_intrinsic_store_var_vec3; break;
- case 4: op = nir_intrinsic_store_var_vec4; break;
- default: assert(0); break;
- }
-
- nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, op);
- nir_deref *store_deref = nir_copy_deref(this->shader, &lhs_deref->deref);
- store->variables[0] = nir_deref_as_var(store_deref);
- store->src[0].reg.reg = reg;
- nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
- return;
- }
-
- if (ir->rhs->as_dereference() || ir->rhs->as_constant()) {
- /* we're copying structs or arrays, so emit a copy_var */
+ if ((ir->rhs->as_dereference() || ir->rhs->as_constant()) &&
+ (ir->write_mask == (1 << num_components) - 1 || ir->write_mask == 0)) {
+ /* We're doing a plain-as-can-be copy, so emit a copy_var */
nir_intrinsic_instr *copy =
nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
ir->rhs->accept(this);
copy->variables[1] = this->deref_head;
- if (ir->condition != NULL) {
- copy->has_predicate = true;
- copy->predicate = evaluate_rvalue(ir->condition);
+
+ if (ir->condition) {
+ nir_if *if_stmt = nir_if_create(this->shader);
+ if_stmt->condition = evaluate_rvalue(ir->condition);
+ nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);
+ nir_instr_insert_after_cf_list(&if_stmt->then_list, ©->instr);
+ } else {
+ nir_instr_insert_after_cf_list(this->cf_node_list, ©->instr);
}
- nir_instr_insert_after_cf_list(this->cf_node_list, ©->instr);
return;
}
assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
- nir_intrinsic_op op;
- switch (ir->lhs->type->vector_elements) {
- case 1: op = nir_intrinsic_store_var_vec1; break;
- case 2: op = nir_intrinsic_store_var_vec2; break;
- case 3: op = nir_intrinsic_store_var_vec3; break;
- case 4: op = nir_intrinsic_store_var_vec4; break;
- default: assert(0); break;
- }
+ ir->lhs->accept(this);
+ nir_deref_var *lhs_deref = this->deref_head;
+ nir_src src = evaluate_rvalue(ir->rhs);
- nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, op);
+ if (ir->write_mask != (1 << num_components) - 1 && ir->write_mask != 0) {
+ /*
+ * We have no good way to update only part of a variable, so just load
+ * the LHS and do a vec operation to combine the old with the new, and
+ * then store it
+ * back into the LHS. Copy propagation should get rid of the mess.
+ */
- ir->lhs->accept(this);
- store->variables[0] = this->deref_head;
- store->src[0] = evaluate_rvalue(ir->rhs);
+ nir_intrinsic_instr *load =
+ nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
+ load->num_components = ir->lhs->type->vector_elements;
+ load->dest.is_ssa = true;
+ nir_ssa_def_init(&load->instr, &load->dest.ssa,
+ num_components, NULL);
+ load->variables[0] = lhs_deref;
+ nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
+
+ nir_op vec_op;
+ switch (ir->lhs->type->vector_elements) {
+ case 1: vec_op = nir_op_imov; break;
+ case 2: vec_op = nir_op_vec2; break;
+ case 3: vec_op = nir_op_vec3; break;
+ case 4: vec_op = nir_op_vec4; break;
+ default: unreachable("Invalid number of components"); break;
+ }
+ nir_alu_instr *vec = nir_alu_instr_create(this->shader, vec_op);
+ vec->dest.dest.is_ssa = true;
+ nir_ssa_def_init(&vec->instr, &vec->dest.dest.ssa,
+ num_components, NULL);
+ vec->dest.write_mask = (1 << num_components) - 1;
+
+ unsigned component = 0;
+ for (unsigned i = 0; i < ir->lhs->type->vector_elements; i++) {
+ if (ir->write_mask & (1 << i)) {
+ vec->src[i].src = src;
+
+ /* GLSL IR will give us the input to the write-masked assignment
+ * in a single packed vector. So, for example, if the
+ * writemask is xzw, then we have to swizzle x -> x, y -> z,
+ * and z -> w and get the y component from the load.
+ */
+ vec->src[i].swizzle[0] = component++;
+ } else {
+ vec->src[i].src.is_ssa = true;
+ vec->src[i].src.ssa = &load->dest.ssa;
+ vec->src[i].swizzle[0] = i;
+ }
+ }
- if (ir->condition != NULL) {
- store->has_predicate = true;
- store->predicate = evaluate_rvalue(ir->condition);
+ nir_instr_insert_after_cf_list(this->cf_node_list, &vec->instr);
+
+ src.is_ssa = true;
+ src.ssa = &vec->dest.dest.ssa;
}
- nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
+ nir_intrinsic_instr *store =
+ nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var);
+ store->num_components = ir->lhs->type->vector_elements;
+ nir_deref *store_deref = nir_copy_deref(this->shader, &lhs_deref->deref);
+ store->variables[0] = nir_deref_as_var(store_deref);
+ store->src[0] = src;
+
+ if (ir->condition) {
+ nir_if *if_stmt = nir_if_create(this->shader);
+ if_stmt->condition = evaluate_rvalue(ir->condition);
+ nir_cf_node_insert_end(this->cf_node_list, &if_stmt->cf_node);
+ nir_instr_insert_after_cf_list(&if_stmt->then_list, &store->instr);
+ } else {
+ nir_instr_insert_after_cf_list(this->cf_node_list, &store->instr);
+ }
}
/*
nir_alu_instr *alu_instr;
nir_intrinsic_instr *intrinsic_instr;
nir_tex_instr *tex_instr;
- nir_load_const_instr *load_const_instr;
switch (instr->type) {
case nir_instr_type_alu:
else
return NULL;
- case nir_instr_type_texture:
- tex_instr = nir_instr_as_texture(instr);
+ case nir_instr_type_tex:
+ tex_instr = nir_instr_as_tex(instr);
return &tex_instr->dest;
- case nir_instr_type_load_const:
- load_const_instr = nir_instr_as_load_const(instr);
- return &load_const_instr->dest;
-
default:
assert(0);
break;
{
nir_dest *dest = get_instr_dest(instr);
- dest->reg.reg = nir_local_reg_create(this->impl);
- dest->reg.reg->num_components = num_components;
+ dest->is_ssa = true;
+ nir_ssa_def_init(instr, &dest->ssa, num_components, NULL);
nir_instr_insert_after_cf_list(this->cf_node_list, instr);
this->result = instr;
* must emit a variable load.
*/
- nir_intrinsic_op op;
- switch (ir->type->vector_elements) {
- case 1:
- op = nir_intrinsic_load_var_vec1;
- break;
- case 2:
- op = nir_intrinsic_load_var_vec2;
- break;
- case 3:
- op = nir_intrinsic_load_var_vec3;
- break;
- case 4:
- op = nir_intrinsic_load_var_vec4;
- break;
- }
-
nir_intrinsic_instr *load_instr =
- nir_intrinsic_instr_create(this->shader, op);
+ nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
+ load_instr->num_components = ir->type->vector_elements;
load_instr->variables[0] = this->deref_head;
add_instr(&load_instr->instr, ir->type->vector_elements);
}
- /*
- * instr doesn't have a destination right now, give it one and then set up
- * the source so that it points to it.
- *
- * TODO: once we support SSA plumb through a use_ssa boolean and use SSA
- * here instead of creating a register.
- */
nir_dest *dest = get_instr_dest(this->result);
- assert(dest->reg.reg);
- nir_src src;
- src.is_ssa = false;
- src.reg.base_offset = 0;
- src.reg.indirect = NULL;
- src.reg.reg = dest->reg.reg;
+ assert(dest->is_ssa);
+ nir_src src;
+ src.is_ssa = true;
+ src.ssa = &dest->ssa;
return src;
}
void
nir_visitor::visit(ir_expression *ir)
{
- if (ir->operation == ir_binop_ubo_load) {
+ /* Some special cases */
+ switch (ir->operation) {
+ case ir_binop_ubo_load: {
ir_constant *const_index = ir->operands[1]->as_constant();
nir_intrinsic_op op;
if (const_index) {
- switch (ir->type->vector_elements) {
- case 1: op = nir_intrinsic_load_ubo_vec1; break;
- case 2: op = nir_intrinsic_load_ubo_vec2; break;
- case 3: op = nir_intrinsic_load_ubo_vec3; break;
- case 4: op = nir_intrinsic_load_ubo_vec4; break;
- default: assert(0); break;
- }
+ op = nir_intrinsic_load_ubo;
} else {
- switch (ir->type->vector_elements) {
- case 1: op = nir_intrinsic_load_ubo_vec1_indirect; break;
- case 2: op = nir_intrinsic_load_ubo_vec2_indirect; break;
- case 3: op = nir_intrinsic_load_ubo_vec3_indirect; break;
- case 4: op = nir_intrinsic_load_ubo_vec4_indirect; break;
- default: assert(0); break;
- }
+ op = nir_intrinsic_load_ubo_indirect;
}
nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
- load->const_index[0] = ir->operands[0]->as_constant()->value.u[0];
- load->const_index[1] = const_index ? const_index->value.u[0] : 0; /* base offset */
- load->const_index[2] = 1; /* number of vec4's */
+ load->num_components = ir->type->vector_elements;
+ load->const_index[0] = const_index ? const_index->value.u[0] : 0; /* base offset */
+ load->const_index[1] = 1; /* number of vec4's */
+ load->src[0] = evaluate_rvalue(ir->operands[0]);
if (!const_index)
- load->src[0] = evaluate_rvalue(ir->operands[1]);
+ load->src[1] = evaluate_rvalue(ir->operands[1]);
add_instr(&load->instr, ir->type->vector_elements);
/*
*/
if (ir->type->base_type == GLSL_TYPE_BOOL) {
- nir_load_const_instr *const_zero = nir_load_const_instr_create(shader);
- const_zero->num_components = 1;
+ nir_load_const_instr *const_zero = nir_load_const_instr_create(shader, 1);
const_zero->value.u[0] = 0;
- const_zero->dest.reg.reg = nir_local_reg_create(this->impl);
- const_zero->dest.reg.reg->num_components = 1;
nir_instr_insert_after_cf_list(this->cf_node_list, &const_zero->instr);
nir_alu_instr *compare = nir_alu_instr_create(shader, nir_op_ine);
- compare->src[0].src.reg.reg = load->dest.reg.reg;
- compare->src[1].src.reg.reg = const_zero->dest.reg.reg;
+ compare->src[0].src.is_ssa = true;
+ compare->src[0].src.ssa = &load->dest.ssa;
+ compare->src[1].src.is_ssa = true;
+ compare->src[1].src.ssa = &const_zero->def;
for (unsigned i = 0; i < ir->type->vector_elements; i++)
compare->src[1].swizzle[i] = 0;
compare->dest.write_mask = (1 << ir->type->vector_elements) - 1;
return;
}
+ case ir_unop_interpolate_at_centroid:
+ case ir_binop_interpolate_at_offset:
+ case ir_binop_interpolate_at_sample: {
+ ir_dereference *deref = ir->operands[0]->as_dereference();
+ ir_swizzle *swizzle = NULL;
+ if (!deref) {
+ /* the api does not allow a swizzle here, but the varying packing code
+ * may have pushed one into here.
+ */
+ swizzle = ir->operands[0]->as_swizzle();
+ assert(swizzle);
+ deref = swizzle->val->as_dereference();
+ assert(deref);
+ }
+
+ deref->accept(this);
+
+ nir_intrinsic_op op;
+ if (this->deref_head->var->data.mode == nir_var_shader_in) {
+ switch (ir->operation) {
+ case ir_unop_interpolate_at_centroid:
+ op = nir_intrinsic_interp_var_at_centroid;
+ break;
+ case ir_binop_interpolate_at_offset:
+ op = nir_intrinsic_interp_var_at_offset;
+ break;
+ case ir_binop_interpolate_at_sample:
+ op = nir_intrinsic_interp_var_at_sample;
+ break;
+ default:
+ unreachable("Invalid interpolation intrinsic");
+ }
+ } else {
+ /* This case can happen if the vertex shader does not write the
+ * given varying. In this case, the linker will lower it to a
+ * global variable. Since interpolating a variable makes no
+ * sense, we'll just turn it into a load which will probably
+ * eventually end up as an SSA definition.
+ */
+ assert(this->deref_head->var->data.mode == nir_var_global);
+ op = nir_intrinsic_load_var;
+ }
+
+ nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(shader, op);
+ intrin->num_components = deref->type->vector_elements;
+ intrin->variables[0] = this->deref_head;
+
+ if (intrin->intrinsic == nir_intrinsic_interp_var_at_offset ||
+ intrin->intrinsic == nir_intrinsic_interp_var_at_sample)
+ intrin->src[0] = evaluate_rvalue(ir->operands[1]);
+
+ add_instr(&intrin->instr, deref->type->vector_elements);
+
+ if (swizzle) {
+ nir_alu_instr *mov = nir_alu_instr_create(shader, nir_op_imov);
+ mov->dest.write_mask = (1 << swizzle->type->vector_elements) - 1;
+ mov->src[0].src.is_ssa = true;
+ mov->src[0].src.ssa = &intrin->dest.ssa;
+
+ mov->src[0].swizzle[0] = swizzle->mask.x;
+ mov->src[0].swizzle[1] = swizzle->mask.y;
+ mov->src[0].swizzle[2] = swizzle->mask.z;
+ mov->src[0].swizzle[3] = swizzle->mask.w;
+ for (unsigned i = deref->type->vector_elements; i < 4; i++)
+ mov->src[0].swizzle[i] = 0;
+
+ add_instr(&mov->instr, swizzle->type->vector_elements);
+ }
+
+ return;
+ }
+
+ default:
+ break;
+ }
+
nir_src srcs[4];
for (unsigned i = 0; i < ir->get_num_operands(); i++)
srcs[i] = evaluate_rvalue(ir->operands[i]);
emit(supports_ints ? nir_op_inot : nir_op_fnot, dest_size, srcs);
break;
case ir_unop_neg:
- instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fmov : nir_op_imov,
+ instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fneg : nir_op_ineg,
dest_size, srcs);
- instr->src[0].negate = true;
break;
case ir_unop_abs:
- instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fmov : nir_op_imov,
+ instr = emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fabs : nir_op_iabs,
dest_size, srcs);
- instr->src[0].abs = true;
break;
case ir_unop_saturate:
assert(types[0] == GLSL_TYPE_FLOAT);
- instr = emit(nir_op_fmov, dest_size, srcs);
- instr->dest.saturate = true;
+ instr = emit(nir_op_fsat, dest_size, srcs);
break;
case ir_unop_sign:
emit(types[0] == GLSL_TYPE_FLOAT ? nir_op_fsign : nir_op_isign,
{
ir->record->accept(this);
- nir_deref_struct *deref = nir_deref_struct_create(this->shader, ir->field);
+ int field_index = this->deref_tail->type->field_index(ir->field);
+ assert(field_index >= 0);
+
+ nir_deref_struct *deref = nir_deref_struct_create(this->shader, field_index);
deref->deref.type = ir->type;
this->deref_tail->child = &deref->deref;
this->deref_tail = &deref->deref;