class nir_visitor : public ir_visitor
{
public:
- nir_visitor(nir_shader *shader, bool supports_ints);
+ nir_visitor(nir_shader *shader, struct gl_shader *sh, gl_shader_stage stage);
~nir_visitor();
virtual void visit(ir_variable *);
virtual void visit(ir_dereference_variable *);
virtual void visit(ir_dereference_record *);
virtual void visit(ir_dereference_array *);
+ virtual void visit(ir_barrier *);
void create_function(ir_function *ir);
bool supports_ints;
+ struct gl_shader *sh;
+
nir_shader *shader;
+ gl_shader_stage stage;
nir_function_impl *impl;
exec_list *cf_node_list;
nir_instr *result; /* result of the expression tree last visited */
+ nir_deref_var *evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir);
+
/* the head of the dereference chain we're creating */
nir_deref_var *deref_head;
/* the tail of the dereference chain we're creating */
}; /* end of anonymous namespace */
nir_shader *
-glsl_to_nir(exec_list *ir, _mesa_glsl_parse_state *state,
- bool native_integers)
+glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
{
- nir_shader *shader = nir_shader_create(NULL);
-
- if (state) {
- shader->num_user_structures = state->num_user_structures;
- shader->user_structures = ralloc_array(shader, glsl_type *,
- shader->num_user_structures);
- memcpy(shader->user_structures, state->user_structures,
- shader->num_user_structures * sizeof(glsl_type *));
- } else {
- shader->num_user_structures = 0;
- shader->user_structures = NULL;
- }
+ nir_shader *shader = nir_shader_create(NULL, options);
- nir_visitor v1(shader, native_integers);
+ nir_visitor v1(shader, sh, sh->Stage);
nir_function_visitor v2(&v1);
- v2.run(ir);
- visit_exec_list(ir, &v1);
+ v2.run(sh->ir);
+ visit_exec_list(sh->ir, &v1);
return shader;
}
-nir_visitor::nir_visitor(nir_shader *shader, bool supports_ints)
+nir_visitor::nir_visitor(nir_shader *shader, struct gl_shader *sh,
+ gl_shader_stage stage)
{
- this->supports_ints = supports_ints;
+ this->supports_ints = shader->options->native_integers;
this->shader = shader;
+ this->sh = sh;
+ this->stage = stage;
this->is_global = true;
this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
_mesa_hash_table_destroy(this->overload_table, NULL);
}
+nir_deref_var *
+nir_visitor::evaluate_deref(nir_instr *mem_ctx, ir_instruction *ir)
+{
+ ir->accept(this);
+ ralloc_steal(mem_ctx, this->deref_head);
+ return this->deref_head;
+}
+
static nir_constant *
constant_copy(ir_constant *ir, void *mem_ctx)
{
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
return ret;
var->data.centroid = ir->data.centroid;
var->data.sample = ir->data.sample;
var->data.invariant = ir->data.invariant;
+ var->data.location = ir->data.location;
switch(ir->data.mode) {
case ir_var_auto:
break;
case ir_var_shader_in:
- var->data.mode = nir_var_shader_in;
+ if (stage == MESA_SHADER_FRAGMENT &&
+ ir->data.location == VARYING_SLOT_FACE) {
+ /* For whatever reason, GLSL IR makes gl_FrontFacing an input */
+ var->data.location = SYSTEM_VALUE_FRONT_FACE;
+ var->data.mode = nir_var_system_value;
+ } else {
+ var->data.mode = nir_var_shader_in;
+ }
break;
case ir_var_shader_out:
var->data.mode = nir_var_uniform;
break;
+ case ir_var_shader_storage:
+ var->data.mode = nir_var_shader_storage;
+ break;
case ir_var_system_value:
var->data.mode = nir_var_system_value;
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
var->data.interpolation = ir->data.interpolation;
var->data.depth_layout = nir_depth_layout_unchanged;
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
- var->data.location = ir->data.location;
var->data.index = ir->data.index;
+ var->data.descriptor_set = ir->data.set;
var->data.binding = ir->data.binding;
/* XXX Get rid of buffer_index */
var->data.atomic.buffer_index = ir->data.binding;
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);
var->constant_initializer = constant_copy(ir->constant_initializer, var);
var->interface_type = ir->get_interface_type();
break;
case nir_var_shader_in:
- _mesa_hash_table_insert(shader->inputs, var->name, var);
+ exec_list_push_tail(&shader->inputs, &var->node);
break;
case nir_var_shader_out:
- _mesa_hash_table_insert(shader->outputs, var->name, var);
+ exec_list_push_tail(&shader->outputs, &var->node);
break;
case nir_var_uniform:
- _mesa_hash_table_insert(shader->uniforms, var->name, var);
+ case nir_var_shader_storage:
+ exec_list_push_tail(&shader->uniforms, &var->node);
break;
case nir_var_system_value:
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
_mesa_hash_table_insert(var_table, ir, var);
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
overload->params[i].type = param->type;
* discards will be immediately followed by a return.
*/
- nir_intrinsic_instr *discard =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+ nir_intrinsic_instr *discard;
+ if (ir->condition) {
+ discard = nir_intrinsic_instr_create(this->shader,
+ nir_intrinsic_discard_if);
+ discard->src[0] = evaluate_rvalue(ir->condition);
+ } else {
+ discard = nir_intrinsic_instr_create(this->shader, nir_intrinsic_discard);
+ }
nir_instr_insert_after_cf_list(this->cf_node_list, &discard->instr);
}
type = nir_jump_continue;
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
nir_jump_instr *instr = nir_jump_instr_create(this->shader, type);
nir_visitor::visit(ir_return *ir)
{
if (ir->value != NULL) {
- ir->value->accept(this);
nir_intrinsic_instr *copy =
nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
- copy->variables[0] = nir_deref_var_create(this->shader,
- this->impl->return_var);
- copy->variables[1] = this->deref_head;
+ copy->variables[0] = nir_deref_var_create(copy, this->impl->return_var);
+ copy->variables[1] = evaluate_deref(©->instr, ir->value);
}
nir_jump_instr *instr = nir_jump_instr_create(this->shader, nir_jump_return);
op = nir_intrinsic_atomic_counter_inc_var;
} else if (strcmp(ir->callee_name(), "__intrinsic_atomic_predecrement") == 0) {
op = nir_intrinsic_atomic_counter_dec_var;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_load") == 0) {
+ op = nir_intrinsic_image_load;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_store") == 0) {
+ op = nir_intrinsic_image_store;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_add") == 0) {
+ op = nir_intrinsic_image_atomic_add;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_min") == 0) {
+ op = nir_intrinsic_image_atomic_min;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_max") == 0) {
+ op = nir_intrinsic_image_atomic_max;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_and") == 0) {
+ op = nir_intrinsic_image_atomic_and;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_or") == 0) {
+ op = nir_intrinsic_image_atomic_or;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_xor") == 0) {
+ op = nir_intrinsic_image_atomic_xor;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_exchange") == 0) {
+ op = nir_intrinsic_image_atomic_exchange;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_atomic_comp_swap") == 0) {
+ op = nir_intrinsic_image_atomic_comp_swap;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_memory_barrier") == 0) {
+ op = nir_intrinsic_memory_barrier;
} else {
- assert(0);
+ unreachable("not reached");
}
- 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;
+
+ switch (op) {
+ case nir_intrinsic_atomic_counter_read_var:
+ case nir_intrinsic_atomic_counter_inc_var:
+ case nir_intrinsic_atomic_counter_dec_var: {
+ ir_dereference *param =
+ (ir_dereference *) ir->actual_parameters.get_head();
+ instr->variables[0] = evaluate_deref(&instr->instr, param);
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
+ break;
+ }
+ case nir_intrinsic_image_load:
+ case nir_intrinsic_image_store:
+ case nir_intrinsic_image_atomic_add:
+ case nir_intrinsic_image_atomic_min:
+ case nir_intrinsic_image_atomic_max:
+ case nir_intrinsic_image_atomic_and:
+ case nir_intrinsic_image_atomic_or:
+ case nir_intrinsic_image_atomic_xor:
+ case nir_intrinsic_image_atomic_exchange:
+ case nir_intrinsic_image_atomic_comp_swap: {
+ nir_ssa_undef_instr *instr_undef =
+ nir_ssa_undef_instr_create(shader, 1);
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &instr_undef->instr);
+
+ /* Set the image variable dereference. */
+ exec_node *param = ir->actual_parameters.get_head();
+ ir_dereference *image = (ir_dereference *)param;
+ const glsl_type *type =
+ image->variable_referenced()->type->without_array();
+
+ instr->variables[0] = evaluate_deref(&instr->instr, image);
+ param = param->get_next();
+
+ /* Set the address argument, extending the coordinate vector to four
+ * components.
+ */
+ const nir_src src_addr = evaluate_rvalue((ir_dereference *)param);
+ nir_alu_instr *instr_addr = nir_alu_instr_create(shader, nir_op_vec4);
+ nir_ssa_dest_init(&instr_addr->instr, &instr_addr->dest.dest, 4, NULL);
+
+ for (int i = 0; i < 4; i++) {
+ if (i < type->coordinate_components()) {
+ instr_addr->src[i].src = src_addr;
+ instr_addr->src[i].swizzle[0] = i;
+ } else {
+ instr_addr->src[i].src = nir_src_for_ssa(&instr_undef->def);
+ }
+ }
+
+ nir_instr_insert_after_cf_list(cf_node_list, &instr_addr->instr);
+ instr->src[0] = nir_src_for_ssa(&instr_addr->dest.dest.ssa);
+ param = param->get_next();
+
+ /* Set the sample argument, which is undefined for single-sample
+ * images.
+ */
+ if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
+ instr->src[1] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ } else {
+ instr->src[1] = nir_src_for_ssa(&instr_undef->def);
+ }
+
+ /* Set the intrinsic parameters. */
+ if (!param->is_tail_sentinel()) {
+ instr->src[2] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ }
+
+ if (!param->is_tail_sentinel()) {
+ instr->src[3] = evaluate_rvalue((ir_dereference *)param);
+ param = param->get_next();
+ }
+
+ /* Set the intrinsic destination. */
+ if (ir->return_deref)
+ nir_ssa_dest_init(&instr->instr, &instr->dest,
+ ir->return_deref->type->vector_elements, NULL);
+ break;
+ }
+ case nir_intrinsic_memory_barrier:
+ break;
+ default:
+ unreachable("not reached");
+ }
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);
+ if (ir->return_deref) {
+ nir_intrinsic_instr *store_instr =
+ nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
+ store_instr->num_components = ir->return_deref->type->vector_elements;
- ir->return_deref->accept(this);
- store_instr->variables[0] = this->deref_head;
- store_instr->src[0].reg.reg = reg;
+ store_instr->variables[0] =
+ evaluate_deref(&store_instr->instr, ir->return_deref);
+ store_instr->src[0] = nir_src_for_ssa(&instr->dest.ssa);
- nir_instr_insert_after_cf_list(this->cf_node_list, &store_instr->instr);
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &store_instr->instr);
+ }
return;
}
unsigned i = 0;
foreach_in_list(ir_dereference, param, &ir->actual_parameters) {
- param->accept(this);
- instr->params[i] = this->deref_head;
+ instr->params[i] = evaluate_deref(&instr->instr, param);
i++;
}
- ir->return_deref->accept(this);
- instr->return_deref = this->deref_head;
+ instr->return_deref = evaluate_deref(&instr->instr, ir->return_deref);
nir_instr_insert_after_cf_list(this->cf_node_list, &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.
- */
+ unsigned num_components = ir->lhs->type->vector_elements;
- 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;
+ 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);
- 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;
+ copy->variables[0] = evaluate_deref(©->instr, ir->lhs);
+ copy->variables[1] = evaluate_deref(©->instr, ir->rhs);
+
+ 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);
}
+ return;
+ }
- 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);
+ assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
- 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);
+ ir->lhs->accept(this);
+ nir_deref_var *lhs_deref = this->deref_head;
+ nir_src src = evaluate_rvalue(ir->rhs);
+ if (ir->write_mask != (1 << num_components) - 1 && ir->write_mask != 0) {
/*
- * 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.
+ * 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.
*/
- 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;
- }
- }
-
- 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);
+ nir_intrinsic_instr *load =
+ nir_intrinsic_instr_create(this->shader, nir_intrinsic_load_var);
+ load->num_components = ir->lhs->type->vector_elements;
+ nir_ssa_dest_init(&load->instr, &load->dest, num_components, NULL);
+ load->variables[0] = lhs_deref;
+ ralloc_steal(load, load->variables[0]);
+ nir_instr_insert_after_cf_list(this->cf_node_list, &load->instr);
+ nir_op vec_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;
+ 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);
+ nir_ssa_dest_init(&vec->instr, &vec->dest.dest, num_components, NULL);
+ vec->dest.write_mask = (1 << num_components) - 1;
- 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 */
- nir_intrinsic_instr *copy =
- nir_intrinsic_instr_create(this->shader, nir_intrinsic_copy_var);
-
- ir->lhs->accept(this);
- copy->variables[0] = this->deref_head;
-
- ir->rhs->accept(this);
- copy->variables[1] = this->deref_head;
-
- if (ir->condition != NULL) {
- copy->has_predicate = true;
- copy->predicate = evaluate_rvalue(ir->condition);
+ 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;
+ }
}
- nir_instr_insert_after_cf_list(this->cf_node_list, ©->instr);
- return;
- }
- assert(ir->rhs->type->is_scalar() || ir->rhs->type->is_vector());
+ nir_instr_insert_after_cf_list(this->cf_node_list, &vec->instr);
- 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;
+ src.is_ssa = true;
+ src.ssa = &vec->dest.dest.ssa;
}
- nir_intrinsic_instr *store = nir_intrinsic_instr_create(this->shader, op);
-
- ir->lhs->accept(this);
- store->variables[0] = this->deref_head;
- store->src[0] = evaluate_rvalue(ir->rhs);
-
- if (ir->condition != NULL) {
- store->has_predicate = true;
- store->predicate = evaluate_rvalue(ir->condition);
+ 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(store, &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_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;
+ unreachable("not reached");
}
return NULL;
{
nir_dest *dest = get_instr_dest(instr);
- dest->reg.reg = nir_local_reg_create(this->impl);
- dest->reg.reg->num_components = num_components;
+ nir_ssa_dest_init(instr, dest, 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;
+ ralloc_steal(load_instr, load_instr->variables[0]);
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);
- return src;
+ return nir_src_for_ssa(&dest->ssa);
}
nir_alu_instr *
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;
}
+
+ ir_constant *const_block = ir->operands[0]->as_constant();
+ assert(const_block && "can't figure out descriptor set index");
+ unsigned index = const_block->value.u[0];
+ unsigned set = sh->UniformBlocks[index].Set;
+ unsigned binding = sh->UniformBlocks[index].Binding;
+
nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
- load->const_index[0] = ir->operands[0]->as_constant()->value.u[0];
+ load->num_components = ir->type->vector_elements;
+ load->const_index[0] = set;
load->const_index[1] = const_index ? const_index->value.u[0] : 0; /* base offset */
- load->const_index[2] = 1; /* number of vec4's */
+ nir_load_const_instr *load_binding = nir_load_const_instr_create(shader, 1);
+ load_binding->value.u[0] = binding;
+ nir_instr_insert_after_cf_list(this->cf_node_list, &load_binding->instr);
+ load->src[0] = nir_src_for_ssa(&load_binding->def);
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;
+ ralloc_steal(intrin, intrin->variables[0]);
+
+ 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,
case ir_unop_rcp: emit(nir_op_frcp, dest_size, srcs); break;
case ir_unop_rsq: emit(nir_op_frsq, dest_size, srcs); break;
case ir_unop_sqrt: emit(nir_op_fsqrt, dest_size, srcs); break;
- case ir_unop_exp: emit(nir_op_fexp, dest_size, srcs); break;
- case ir_unop_log: emit(nir_op_flog, dest_size, srcs); break;
+ case ir_unop_exp: unreachable("ir_unop_exp should have been lowered");
+ case ir_unop_log: unreachable("ir_unop_log should have been lowered");
case ir_unop_exp2: emit(nir_op_fexp2, dest_size, srcs); break;
case ir_unop_log2: emit(nir_op_flog2, dest_size, srcs); break;
case ir_unop_i2f:
case ir_unop_bitcast_f2i:
case ir_unop_bitcast_u2f:
case ir_unop_bitcast_f2u:
+ case ir_unop_subroutine_to_int:
/* no-op */
emit(nir_op_imov, dest_size, srcs);
break;
dest_size, srcs);
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
break;
case ir_unop_trunc: emit(nir_op_ftrunc, dest_size, srcs); break;
case ir_unop_round_even: emit(nir_op_fround_even, dest_size, srcs); break;
case ir_unop_sin: emit(nir_op_fsin, dest_size, srcs); break;
case ir_unop_cos: emit(nir_op_fcos, dest_size, srcs); break;
- case ir_unop_sin_reduced:
- emit(nir_op_fsin_reduced, dest_size, srcs);
- break;
- case ir_unop_cos_reduced:
- emit(nir_op_fcos_reduced, dest_size, srcs);
- break;
case ir_unop_dFdx: emit(nir_op_fddx, dest_size, srcs); break;
case ir_unop_dFdy: emit(nir_op_fddy, dest_size, srcs); break;
case ir_unop_dFdx_fine: emit(nir_op_fddx_fine, dest_size, srcs); break;
case 2: emit(nir_op_fnoise1_2, dest_size, srcs); break;
case 3: emit(nir_op_fnoise1_3, dest_size, srcs); break;
case 4: emit(nir_op_fnoise1_4, dest_size, srcs); break;
- default: assert(0); break;
+ default: unreachable("not reached");
}
break;
case 2:
case 2: emit(nir_op_fnoise2_2, dest_size, srcs); break;
case 3: emit(nir_op_fnoise2_3, dest_size, srcs); break;
case 4: emit(nir_op_fnoise2_4, dest_size, srcs); break;
- default: assert(0); break;
+ default: unreachable("not reached");
}
break;
case 3:
case 2: emit(nir_op_fnoise3_2, dest_size, srcs); break;
case 3: emit(nir_op_fnoise3_3, dest_size, srcs); break;
case 4: emit(nir_op_fnoise3_4, dest_size, srcs); break;
- default: assert(0); break;
+ default: unreachable("not reached");
}
break;
case 4:
case 2: emit(nir_op_fnoise4_2, dest_size, srcs); break;
case 3: emit(nir_op_fnoise4_3, dest_size, srcs); break;
case 4: emit(nir_op_fnoise4_4, dest_size, srcs); break;
- default: assert(0); break;
+ default: unreachable("not reached");
}
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
break;
case ir_binop_add:
case ir_binop_bit_and:
case ir_binop_bit_or:
case ir_binop_bit_xor:
+ case ir_binop_logic_and:
+ case ir_binop_logic_or:
+ case ir_binop_logic_xor:
case ir_binop_lshift:
case ir_binop_rshift:
switch (ir->operation) {
case ir_binop_bit_xor:
op = nir_op_ixor;
break;
+ case ir_binop_logic_and:
+ if (supports_ints)
+ op = nir_op_iand;
+ else
+ op = nir_op_fand;
+ break;
+ case ir_binop_logic_or:
+ if (supports_ints)
+ op = nir_op_ior;
+ else
+ op = nir_op_for;
+ break;
+ case ir_binop_logic_xor:
+ if (supports_ints)
+ op = nir_op_ixor;
+ else
+ op = nir_op_fxor;
+ break;
case ir_binop_lshift:
op = nir_op_ishl;
break;
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
instr = emit(op, dest_size, srcs);
case 3: emit(nir_op_ball_fequal3, dest_size, srcs); break;
case 4: emit(nir_op_ball_fequal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
} else {
switch (ir->operands[0]->type->vector_elements) {
case 3: emit(nir_op_ball_iequal3, dest_size, srcs); break;
case 4: emit(nir_op_ball_iequal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
}
} else {
case 3: emit(nir_op_fall_equal3, dest_size, srcs); break;
case 4: emit(nir_op_fall_equal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
}
break;
case 3: emit(nir_op_bany_fnequal3, dest_size, srcs); break;
case 4: emit(nir_op_bany_fnequal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
} else {
switch (ir->operands[0]->type->vector_elements) {
case 3: emit(nir_op_bany_inequal3, dest_size, srcs); break;
case 4: emit(nir_op_bany_inequal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
}
} else {
case 3: emit(nir_op_fany_nequal3, dest_size, srcs); break;
case 4: emit(nir_op_fany_nequal4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
}
break;
- case ir_binop_logic_and:
- if (supports_ints)
- emit(nir_op_iand, dest_size, srcs);
- else
- emit(nir_op_fand, dest_size, srcs);
- break;
- case ir_binop_logic_or:
- if (supports_ints)
- emit(nir_op_ior, dest_size, srcs);
- else
- emit(nir_op_for, dest_size, srcs);
- break;
- case ir_binop_logic_xor:
- if (supports_ints)
- emit(nir_op_ixor, dest_size, srcs);
- else
- emit(nir_op_fxor, dest_size, srcs);
- break;
case ir_binop_dot:
switch (ir->operands[0]->type->vector_elements) {
case 2: emit(nir_op_fdot2, dest_size, srcs); break;
case 3: emit(nir_op_fdot3, dest_size, srcs); break;
case 4: emit(nir_op_fdot4, dest_size, srcs); break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
break;
case 2: emit(nir_op_vec2, dest_size, srcs); break;
case 3: emit(nir_op_vec3, dest_size, srcs); break;
case 4: emit(nir_op_vec4, dest_size, srcs); break;
- default: assert(0); break;
+ default: unreachable("not reached");
}
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
}
break;
default:
- assert(0);
- break;
+ unreachable("not reached");
}
if (ir->projector != NULL)
instr->dest_type = nir_type_unsigned;
break;
default:
- assert(0);
+ unreachable("not reached");
}
- ir->sampler->accept(this);
- instr->sampler = this->deref_head;
+ instr->sampler = evaluate_deref(&instr->instr, ir->sampler);
unsigned src_number = 0;
if (ir->coordinate != NULL) {
instr->coord_components = ir->coordinate->type->vector_elements;
- instr->src[src_number] = evaluate_rvalue(ir->coordinate);
- instr->src_type[src_number] = nir_tex_src_coord;
+ instr->src[src_number].src = evaluate_rvalue(ir->coordinate);
+ instr->src[src_number].src_type = nir_tex_src_coord;
src_number++;
}
if (ir->projector != NULL) {
- instr->src[src_number] = evaluate_rvalue(ir->projector);
- instr->src_type[src_number] = nir_tex_src_projector;
+ instr->src[src_number].src = evaluate_rvalue(ir->projector);
+ instr->src[src_number].src_type = nir_tex_src_projector;
src_number++;
}
if (ir->shadow_comparitor != NULL) {
- instr->src[src_number] = evaluate_rvalue(ir->shadow_comparitor);
- instr->src_type[src_number] = nir_tex_src_comparitor;
+ instr->src[src_number].src = evaluate_rvalue(ir->shadow_comparitor);
+ instr->src[src_number].src_type = nir_tex_src_comparitor;
src_number++;
}
for (unsigned i = 0; i < const_offset->type->vector_elements; i++)
instr->const_offset[i] = const_offset->value.i[i];
} else {
- instr->src[src_number] = evaluate_rvalue(ir->offset);
- instr->src_type[src_number] = nir_tex_src_offset;
+ instr->src[src_number].src = evaluate_rvalue(ir->offset);
+ instr->src[src_number].src_type = nir_tex_src_offset;
src_number++;
}
}
switch (ir->op) {
case ir_txb:
- instr->src[src_number] = evaluate_rvalue(ir->lod_info.bias);
- instr->src_type[src_number] = nir_tex_src_bias;
+ instr->src[src_number].src = evaluate_rvalue(ir->lod_info.bias);
+ instr->src[src_number].src_type = nir_tex_src_bias;
src_number++;
break;
case ir_txf:
case ir_txs:
if (ir->lod_info.lod != NULL) {
- instr->src[src_number] = evaluate_rvalue(ir->lod_info.lod);
- instr->src_type[src_number] = nir_tex_src_lod;
+ instr->src[src_number].src = evaluate_rvalue(ir->lod_info.lod);
+ instr->src[src_number].src_type = nir_tex_src_lod;
src_number++;
}
break;
case ir_txd:
- instr->src[src_number] = evaluate_rvalue(ir->lod_info.grad.dPdx);
- instr->src_type[src_number] = nir_tex_src_ddx;
+ instr->src[src_number].src = evaluate_rvalue(ir->lod_info.grad.dPdx);
+ instr->src[src_number].src_type = nir_tex_src_ddx;
src_number++;
- instr->src[src_number] = evaluate_rvalue(ir->lod_info.grad.dPdy);
- instr->src_type[src_number] = nir_tex_src_ddy;
+ instr->src[src_number].src = evaluate_rvalue(ir->lod_info.grad.dPdy);
+ instr->src[src_number].src_type = nir_tex_src_ddy;
src_number++;
break;
case ir_txf_ms:
- instr->src[src_number] = evaluate_rvalue(ir->lod_info.sample_index);
- instr->src_type[src_number] = nir_tex_src_ms_index;
+ instr->src[src_number].src = evaluate_rvalue(ir->lod_info.sample_index);
+ instr->src[src_number].src_type = nir_tex_src_ms_index;
src_number++;
break;
{
/*
* We don't know if this variable is an an array or struct that gets
- * dereferenced, so do the safe thing an make it a variable and return a
- * dereference.
+ * dereferenced, so do the safe thing an make it a variable with a
+ * constant initializer and return a dereference.
*/
nir_variable *var = ralloc(this->shader, nir_variable);
var->type = ir->type;
var->data.mode = nir_var_local;
var->data.read_only = true;
- var->constant_value = constant_copy(ir, var);
var->constant_initializer = constant_copy(ir, var);
exec_list_push_tail(&this->impl->locals, &var->node);
{
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->deref_tail, field_index);
deref->deref.type = ir->type;
this->deref_tail->child = &deref->deref;
this->deref_tail = &deref->deref;
ir->array->accept(this);
this->deref_tail->child = &deref->deref;
+ ralloc_steal(this->deref_tail, deref);
this->deref_tail = &deref->deref;
}
+
+void
+nir_visitor::visit(ir_barrier *ir)
+{
+ nir_intrinsic_instr *instr =
+ nir_intrinsic_instr_create(this->shader, nir_intrinsic_barrier);
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+}