Merge remote-tracking branch 'mesa-public/master' into vulkan
[mesa.git] / src / glsl / nir / glsl_to_nir.cpp
index df8a18a7f49210738332aa81e10726064ab1c078..5a1bbc43243d0100a1f428e590c5ca934a90b8a6 100644 (file)
@@ -46,7 +46,7 @@ namespace {
 class nir_visitor : public ir_visitor
 {
 public:
-   nir_visitor(nir_shader *shader);
+   nir_visitor(nir_shader *shader, gl_shader *sh);
    ~nir_visitor();
 
    virtual void visit(ir_variable *);
@@ -70,10 +70,9 @@ public:
    virtual void visit(ir_dereference_array *);
    virtual void visit(ir_barrier *);
 
-   void create_function(ir_function *ir);
+   void create_function(ir_function_signature *ir);
 
 private:
-   void create_overload(ir_function_signature *ir, nir_function *function);
    void add_instr(nir_instr *instr, unsigned num_components);
    nir_ssa_def *evaluate_rvalue(ir_rvalue *ir);
 
@@ -86,6 +85,8 @@ private:
 
    bool supports_ints;
 
+   struct gl_shader *sh;
+
    nir_shader *shader;
    nir_function_impl *impl;
    nir_builder b;
@@ -139,12 +140,21 @@ glsl_to_nir(const struct gl_shader_program *shader_prog,
 
    nir_shader *shader = nir_shader_create(NULL, stage, options);
 
-   nir_visitor v1(shader);
+   nir_visitor v1(shader, sh);
    nir_function_visitor v2(&v1);
    v2.run(sh->ir);
    visit_exec_list(sh->ir, &v1);
 
-   nir_lower_outputs_to_temporaries(shader);
+   nir_function *main = NULL;
+   nir_foreach_function(shader, func) {
+      if (strcmp(func->name, "main") == 0) {
+         main = func;
+         break;
+      }
+   }
+   assert(main);
+
+   nir_lower_outputs_to_temporaries(shader, main);
 
    shader->info.name = ralloc_asprintf(shader, "GLSL%d", shader_prog->Name);
    if (shader_prog->Label)
@@ -205,10 +215,11 @@ glsl_to_nir(const struct gl_shader_program *shader_prog,
    return shader;
 }
 
-nir_visitor::nir_visitor(nir_shader *shader)
+nir_visitor::nir_visitor(nir_shader *shader, gl_shader *sh)
 {
    this->supports_ints = shader->options->native_integers;
    this->shader = shader;
+   this->sh = sh;
    this->is_global = true;
    this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
                                              _mesa_key_pointer_equal);
@@ -389,8 +400,9 @@ nir_visitor::visit(ir_variable *ir)
    }
 
    var->data.index = ir->data.index;
+   var->data.descriptor_set = 0;
    var->data.binding = ir->data.binding;
-   var->data.atomic.offset = ir->data.atomic.offset;
+   var->data.offset = ir->data.offset;
    var->data.image.read_only = ir->data.image_read_only;
    var->data.image.write_only = ir->data.image_write_only;
    var->data.image.coherent = ir->data.image_coherent;
@@ -430,60 +442,50 @@ nir_visitor::visit(ir_variable *ir)
 ir_visitor_status
 nir_function_visitor::visit_enter(ir_function *ir)
 {
-   visitor->create_function(ir);
-   return visit_continue_with_parent;
-}
-
-
-void
-nir_visitor::create_function(ir_function *ir)
-{
-   nir_function *func = nir_function_create(this->shader, ir->name);
    foreach_in_list(ir_function_signature, sig, &ir->signatures) {
-      create_overload(sig, func);
+      visitor->create_function(sig);
    }
+   return visit_continue_with_parent;
 }
 
-
-
 void
-nir_visitor::create_overload(ir_function_signature *ir, nir_function *function)
+nir_visitor::create_function(ir_function_signature *ir)
 {
    if (ir->is_intrinsic)
       return;
 
-   nir_function_overload *overload = nir_function_overload_create(function);
+   nir_function *func = nir_function_create(shader, ir->function_name());
 
    unsigned num_params = ir->parameters.length();
-   overload->num_params = num_params;
-   overload->params = ralloc_array(shader, nir_parameter, num_params);
+   func->num_params = num_params;
+   func->params = ralloc_array(shader, nir_parameter, num_params);
 
    unsigned i = 0;
    foreach_in_list(ir_variable, param, &ir->parameters) {
       switch (param->data.mode) {
       case ir_var_function_in:
-         overload->params[i].param_type = nir_parameter_in;
+         func->params[i].param_type = nir_parameter_in;
          break;
 
       case ir_var_function_out:
-         overload->params[i].param_type = nir_parameter_out;
+         func->params[i].param_type = nir_parameter_out;
          break;
 
       case ir_var_function_inout:
-         overload->params[i].param_type = nir_parameter_inout;
+         func->params[i].param_type = nir_parameter_inout;
          break;
 
       default:
          unreachable("not reached");
       }
 
-      overload->params[i].type = param->type;
+      func->params[i].type = param->type;
       i++;
    }
 
-   overload->return_type = ir->return_type;
+   func->return_type = ir->return_type;
 
-   _mesa_hash_table_insert(this->overload_table, ir, overload);
+   _mesa_hash_table_insert(this->overload_table, ir, func);
 }
 
 void
@@ -503,13 +505,13 @@ nir_visitor::visit(ir_function_signature *ir)
       _mesa_hash_table_search(this->overload_table, ir);
 
    assert(entry);
-   nir_function_overload *overload = (nir_function_overload *) entry->data;
+   nir_function *func = (nir_function *) entry->data;
 
    if (ir->is_defined) {
-      nir_function_impl *impl = nir_function_impl_create(overload);
+      nir_function_impl *impl = nir_function_impl_create(func);
       this->impl = impl;
 
-      unsigned num_params = overload->num_params;
+      unsigned num_params = func->num_params;
       impl->num_params = num_params;
       impl->params = ralloc_array(this->shader, nir_variable *, num_params);
       unsigned i = 0;
@@ -519,13 +521,13 @@ nir_visitor::visit(ir_function_signature *ir)
          i++;
       }
 
-      if (overload->return_type == glsl_type::void_type) {
+      if (func->return_type == glsl_type::void_type) {
          impl->return_var = NULL;
       } else {
          impl->return_var = ralloc(this->shader, nir_variable);
          impl->return_var->name = ralloc_strdup(impl->return_var,
                                                 "return_var");
-         impl->return_var->type = overload->return_type;
+         impl->return_var->type = func->return_type;
       }
 
       this->is_global = false;
@@ -536,7 +538,7 @@ nir_visitor::visit(ir_function_signature *ir)
 
       this->is_global = true;
    } else {
-      overload->impl = NULL;
+      func->impl = NULL;
    }
 }
 
@@ -1067,6 +1069,7 @@ nir_visitor::visit(ir_call *ir)
          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->const_index[0] = (1 << store_instr->num_components) - 1;
 
          store_instr->variables[0] =
             evaluate_deref(&store_instr->instr, ir->return_deref);
@@ -1081,7 +1084,7 @@ nir_visitor::visit(ir_call *ir)
    struct hash_entry *entry =
       _mesa_hash_table_search(this->overload_table, ir->callee);
    assert(entry);
-   nir_function_overload *callee = (nir_function_overload *) entry->data;
+   nir_function *callee = (nir_function *) entry->data;
 
    nir_call_instr *instr = nir_call_instr_create(this->shader, callee);
 
@@ -1128,43 +1131,23 @@ nir_visitor::visit(ir_assignment *ir)
    nir_ssa_def *src = evaluate_rvalue(ir->rhs);
 
    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.
+      /* 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.
        */
-
-      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_builder_instr_insert(&b, &load->instr);
-
-      nir_ssa_def *srcs[4];
-
+      unsigned swiz[4];
       unsigned component = 0;
-      for (unsigned i = 0; i < ir->lhs->type->vector_elements; i++) {
-         if (ir->write_mask & (1 << i)) {
-            /* 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.
-             */
-            srcs[i] = nir_channel(&b, src, component++);
-         } else {
-            srcs[i] = nir_channel(&b, &load->dest.ssa, i);
-         }
+      for (unsigned i = 0; i < 4; i++) {
+         swiz[i] = ir->write_mask & (1 << i) ? component++ : 0;
       }
-
-      src = nir_vec(&b, srcs, ir->lhs->type->vector_elements);
+      src = nir_swizzle(&b, src, swiz, num_components, !supports_ints);
    }
 
    nir_intrinsic_instr *store =
       nir_intrinsic_instr_create(this->shader, nir_intrinsic_store_var);
    store->num_components = ir->lhs->type->vector_elements;
+   store->const_index[0] = ir->write_mask;
    nir_deref *store_deref = nir_copy_deref(store, &lhs_deref->deref);
    store->variables[0] = nir_deref_as_var(store_deref);
    store->src[0] = nir_src_for_ssa(src);
@@ -1751,7 +1734,6 @@ nir_visitor::visit(ir_expression *ir)
    case ir_binop_pack_half_2x16_split:
          result = nir_pack_half_2x16_split(&b, srcs[0], srcs[1]);
          break;
-   case ir_binop_bfm:   result = nir_bfm(&b, srcs[0], srcs[1]);   break;
    case ir_binop_ldexp: result = nir_ldexp(&b, srcs[0], srcs[1]); break;
    case ir_triop_fma:
       result = nir_ffma(&b, srcs[0], srcs[1], srcs[2]);
@@ -1765,9 +1747,6 @@ nir_visitor::visit(ir_expression *ir)
       else
          result = nir_fcsel(&b, srcs[0], srcs[1], srcs[2]);
       break;
-   case ir_triop_bfi:
-      result = nir_bfi(&b, srcs[0], srcs[1], srcs[2]);
-      break;
    case ir_triop_bitfield_extract:
       result = (out_type == GLSL_TYPE_INT) ?
          nir_ibitfield_extract(&b, srcs[0], srcs[1], srcs[2]) :