*/
#include "glsl_to_nir.h"
+#include "nir_control_flow.h"
#include "ir_visitor.h"
#include "ir_hierarchical_visitor.h"
#include "ir.h"
class nir_visitor : public ir_visitor
{
public:
- nir_visitor(nir_shader *shader, gl_shader_stage stage);
+ nir_visitor(nir_shader *shader);
~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;
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_shader *
glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
{
- nir_shader *shader = nir_shader_create(NULL, options);
+ nir_shader *shader = nir_shader_create(NULL, sh->Stage, options);
- nir_visitor v1(shader, sh->Stage);
+ nir_visitor v1(shader);
nir_function_visitor v2(&v1);
v2.run(sh->ir);
visit_exec_list(sh->ir, &v1);
+ nir_lower_outputs_to_temporaries(shader);
+
+ shader->gs.vertices_out = sh->Geom.VerticesOut;
+ shader->gs.invocations = sh->Geom.Invocations;
+
return shader;
}
-nir_visitor::nir_visitor(nir_shader *shader, gl_shader_stage stage)
+nir_visitor::nir_visitor(nir_shader *shader)
{
this->supports_ints = shader->options->native_integers;
this->shader = shader;
- this->stage = stage;
this->is_global = true;
this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
break;
case ir_var_shader_in:
- if (stage == MESA_SHADER_FRAGMENT &&
+ if (shader->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_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;
case nir_var_uniform:
+ case nir_var_shader_storage:
exec_list_push_tail(&shader->uniforms, &var->node);
break;
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 if (strcmp(ir->callee_name(), "__intrinsic_image_size") == 0) {
+ op = nir_intrinsic_image_size;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_image_samples") == 0) {
+ op = nir_intrinsic_image_samples;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_store_ssbo") == 0) {
+ op = nir_intrinsic_store_ssbo;
+ } else if (strcmp(ir->callee_name(), "__intrinsic_load_ssbo") == 0) {
+ op = nir_intrinsic_load_ssbo;
} else {
unreachable("not reached");
}
nir_intrinsic_instr *instr = nir_intrinsic_instr_create(shader, op);
- 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);
+ nir_dest *dest = &instr->dest;
+
+ 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);
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ 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:
+ case nir_intrinsic_image_samples:
+ case nir_intrinsic_image_size: {
+ 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 intrinsic destination. */
+ if (ir->return_deref) {
+ const nir_intrinsic_info *info =
+ &nir_intrinsic_infos[instr->intrinsic];
+ nir_ssa_dest_init(&instr->instr, &instr->dest,
+ info->dest_components, NULL);
+ }
+
+ if (op == nir_intrinsic_image_size ||
+ op == nir_intrinsic_image_samples) {
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ break;
+ }
+
+ /* 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();
+ }
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ break;
+ }
+ case nir_intrinsic_memory_barrier:
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ break;
+ case nir_intrinsic_store_ssbo: {
+ exec_node *param = ir->actual_parameters.get_head();
+ ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
+
+ param = param->get_next();
+ ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
+
+ param = param->get_next();
+ ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
+
+ param = param->get_next();
+ ir_constant *write_mask = ((ir_instruction *)param)->as_constant();
+ assert(write_mask);
+
+ /* Check if we need the indirect version */
+ ir_constant *const_offset = offset->as_constant();
+ if (!const_offset) {
+ op = nir_intrinsic_store_ssbo_indirect;
+ ralloc_free(instr);
+ instr = nir_intrinsic_instr_create(shader, op);
+ instr->src[2] = evaluate_rvalue(offset);
+ instr->const_index[0] = 0;
+ dest = &instr->dest;
+ } else {
+ instr->const_index[0] = const_offset->value.u[0];
+ }
+
+ instr->const_index[1] = write_mask->value.u[0];
+
+ instr->src[0] = evaluate_rvalue(val);
+ instr->num_components = val->type->vector_elements;
+
+ instr->src[1] = evaluate_rvalue(block);
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ break;
+ }
+ case nir_intrinsic_load_ssbo: {
+ exec_node *param = ir->actual_parameters.get_head();
+ ir_rvalue *block = ((ir_instruction *)param)->as_rvalue();
+
+ param = param->get_next();
+ ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
+
+ /* Check if we need the indirect version */
+ ir_constant *const_offset = offset->as_constant();
+ if (!const_offset) {
+ op = nir_intrinsic_load_ssbo_indirect;
+ ralloc_free(instr);
+ instr = nir_intrinsic_instr_create(shader, op);
+ instr->src[1] = evaluate_rvalue(offset);
+ instr->const_index[0] = 0;
+ dest = &instr->dest;
+ } else {
+ instr->const_index[0] = const_offset->value.u[0];
+ }
+
+ instr->src[0] = evaluate_rvalue(block);
+
+ const glsl_type *type = ir->return_deref->var->type;
+ instr->num_components = type->vector_elements;
+
+ /* Setup destination register */
+ nir_ssa_dest_init(&instr->instr, &instr->dest,
+ type->vector_elements, NULL);
+
+ /* Insert the created nir instruction now since in the case of boolean
+ * result we will need to emit another instruction after it
+ */
+ nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+
+ /*
+ * In SSBO/UBO's, a true boolean value is any non-zero value, but we
+ * consider a true boolean to be ~0. Fix this up with a != 0
+ * comparison.
+ */
+ if (type->base_type == GLSL_TYPE_BOOL) {
+ nir_load_const_instr *const_zero =
+ nir_load_const_instr_create(shader, 1);
+ const_zero->value.u[0] = 0;
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &const_zero->instr);
+
+ nir_alu_instr *load_ssbo_compare =
+ nir_alu_instr_create(shader, nir_op_ine);
+ load_ssbo_compare->src[0].src.is_ssa = true;
+ load_ssbo_compare->src[0].src.ssa = &instr->dest.ssa;
+ load_ssbo_compare->src[1].src.is_ssa = true;
+ load_ssbo_compare->src[1].src.ssa = &const_zero->def;
+ for (unsigned i = 0; i < type->vector_elements; i++)
+ load_ssbo_compare->src[1].swizzle[i] = 0;
+ nir_ssa_dest_init(&load_ssbo_compare->instr,
+ &load_ssbo_compare->dest.dest,
+ type->vector_elements, NULL);
+ load_ssbo_compare->dest.write_mask = (1 << type->vector_elements) - 1;
+ nir_instr_insert_after_cf_list(this->cf_node_list,
+ &load_ssbo_compare->instr);
+ dest = &load_ssbo_compare->dest.dest;
+ }
- nir_instr_insert_after_cf_list(this->cf_node_list, &instr->instr);
+ break;
+ }
+ default:
+ unreachable("not reached");
+ }
- nir_intrinsic_instr *store_instr =
- nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
- store_instr->num_components = 1;
+ 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;
- store_instr->variables[0] = evaluate_deref(&store_instr->instr, ir->return_deref);
- store_instr->src[0].is_ssa = true;
- store_instr->src[0].ssa = &instr->dest.ssa;
+ store_instr->variables[0] =
+ evaluate_deref(&store_instr->instr, ir->return_deref);
+ store_instr->src[0] = nir_src_for_ssa(&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;
}
}
nir_dest *dest = get_instr_dest(this->result);
-
assert(dest->is_ssa);
- nir_src src = NIR_SRC_INIT;
- src.is_ssa = true;
- src.ssa = &dest->ssa;
- return src;
+ return nir_src_for_ssa(&dest->ssa);
}
nir_alu_instr *
nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
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[1] = evaluate_rvalue(ir->operands[1]);
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;
unreachable("not reached");
}
break;
+ case ir_unop_get_buffer_size: {
+ nir_intrinsic_instr *load = nir_intrinsic_instr_create(
+ this->shader,
+ nir_intrinsic_get_buffer_size);
+ load->num_components = ir->type->vector_elements;
+ load->src[0] = evaluate_rvalue(ir->operands[0]);
+ add_instr(&load->instr, ir->type->vector_elements);
+ return;
+ }
+
case ir_binop_add:
case ir_binop_sub:
case ir_binop_mul:
num_srcs = 0;
break;
+ case ir_texture_samples:
+ op = nir_texop_texture_samples;
+ num_srcs = 0;
+ break;
+
default:
unreachable("not reached");
}
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);
+}