program: Remove NV_fragment_program_option parsing support.
[mesa.git] / src / mesa / program / prog_to_nir.c
index 5ca81e54b7f2a973463a47d5e56f4b943eff3a3e..1f916ab92992eed5c19b287b4d0d586023ca4290 100644 (file)
@@ -23,9 +23,9 @@
  * IN THE SOFTWARE.
  */
 
-#include "nir/nir.h"
-#include "nir/nir_builder.h"
-#include "glsl/list.h"
+#include "compiler/nir/nir.h"
+#include "compiler/nir/nir_builder.h"
+#include "compiler/glsl/list.h"
 #include "main/imports.h"
 #include "util/ralloc.h"
 
@@ -33,6 +33,7 @@
 #include "prog_instruction.h"
 #include "prog_parameter.h"
 #include "prog_print.h"
+#include "program.h"
 
 /**
  * \file prog_to_nir.c
@@ -142,7 +143,7 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
       load->variables[0] = nir_deref_var_create(load, c->input_vars[prog_src->Index]);
 
       nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
-      nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+      nir_builder_instr_insert(b, &load->instr);
 
       src.src = nir_src_for_ssa(&load->dest.ssa);
       break;
@@ -166,6 +167,8 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
          }
          /* FALLTHROUGH */
       case PROGRAM_STATE_VAR: {
+         assert(c->parameters != NULL);
+
          nir_intrinsic_instr *load =
             nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_var);
          nir_ssa_dest_init(&load->instr, &load->dest, 4, NULL);
@@ -200,7 +203,7 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
             deref_arr->base_offset = prog_src->Index;
          }
 
-         nir_instr_insert_after_cf_list(b->cf_node_list, &load->instr);
+         nir_builder_instr_insert(b, &load->instr);
 
          src.src = nir_src_for_ssa(&load->dest.ssa);
          break;
@@ -227,9 +230,6 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
 
       def = nir_fmov_alu(b, src, 4);
 
-      if (prog_src->Abs)
-         def = nir_fabs(b, def);
-
       if (prog_src->Negate)
          def = nir_fneg(b, def);
    } else {
@@ -250,14 +250,11 @@ ptn_get_src(struct ptn_compile *c, const struct prog_src_register *prog_src)
             mov->dest.write_mask = 0x1;
             mov->src[0] = src;
             mov->src[0].swizzle[0] = swizzle;
-            nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+            nir_builder_instr_insert(b, &mov->instr);
 
             chans[i] = &mov->dest.dest.ssa;
          }
 
-         if (prog_src->Abs)
-            chans[i] = nir_fabs(b, chans[i]);
-
          if (prog_src->Negate & (1 << i))
             chans[i] = nir_fneg(b, chans[i]);
       }
@@ -278,7 +275,7 @@ ptn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)
       instr->src[i].src = nir_src_for_ssa(src[i]);
 
    instr->dest = dest;
-   nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+   nir_builder_instr_insert(b, &instr->instr);
 }
 
 static void
@@ -297,7 +294,7 @@ ptn_move_dest_masked(nir_builder *b, nir_alu_dest dest,
    mov->src[0].src = nir_src_for_ssa(def);
    for (unsigned i = def->num_components; i < 4; i++)
       mov->src[0].swizzle[i] = def->num_components - 1;
-   nir_instr_insert_after_cf_list(b->cf_node_list, &mov->instr);
+   nir_builder_instr_insert(b, &mov->instr);
 }
 
 static void
@@ -524,8 +521,7 @@ ptn_dp4(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
 static void
 ptn_dph(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
 {
-   nir_ssa_def *dp3 = nir_fdot3(b, src[0], src[1]);
-   ptn_move_dest(b, dest, nir_fadd(b, dp3, ptn_channel(b, src[1], W)));
+   ptn_move_dest(b, dest, nir_fdph(b, src[0], src[1]));
 }
 
 static void
@@ -552,13 +548,13 @@ static void
 ptn_kil(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src)
 {
    nir_ssa_def *cmp = b->shader->options->native_integers ?
-      nir_bany4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0))) :
-      nir_fany4(b, nir_slt(b, src[0], nir_imm_float(b, 0.0)));
+      nir_bany_inequal4(b, nir_flt(b, src[0], nir_imm_float(b, 0.0)), nir_imm_int(b, 0)) :
+      nir_fany_nequal4(b, nir_slt(b, src[0], nir_imm_float(b, 0.0)), nir_imm_float(b, 0.0));
 
    nir_intrinsic_instr *discard =
       nir_intrinsic_instr_create(b->shader, nir_intrinsic_discard_if);
    discard->src[0] = nir_src_for_ssa(cmp);
-   nir_instr_insert_after_cf_list(b->cf_node_list, &discard->instr);
+   nir_builder_instr_insert(b, &discard->instr);
 }
 
 static void
@@ -590,11 +586,6 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
       op = nir_texop_tex;
       num_srcs = 2;
       break;
-   case OPCODE_TXP_NV:
-      assert(!"not handled");
-      op = nir_texop_tex;
-      num_srcs = 2;
-      break;
    default:
       fprintf(stderr, "unknown tex op %d\n", prog_inst->Opcode);
       abort();
@@ -607,6 +598,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
    instr->op = op;
    instr->dest_type = nir_type_float;
    instr->is_shadow = prog_inst->TexShadow;
+   instr->texture_index = prog_inst->TexSrcUnit;
    instr->sampler_index = prog_inst->TexSrcUnit;
 
    switch (prog_inst->TexSrcTarget) {
@@ -685,7 +677,7 @@ ptn_tex(nir_builder *b, nir_alu_dest dest, nir_ssa_def **src,
    assert(src_number == num_srcs);
 
    nir_ssa_dest_init(&instr->instr, &instr->dest, 4, NULL);
-   nir_instr_insert_after_cf_list(b->cf_node_list, &instr->instr);
+   nir_builder_instr_insert(b, &instr->instr);
 
    /* Resolve the writemask on the texture op. */
    ptn_move_dest(b, dest, &instr->dest.ssa);
@@ -697,7 +689,7 @@ static const nir_op op_trans[MAX_OPCODE] = {
    [OPCODE_ADD] = nir_op_fadd,
    [OPCODE_ARL] = 0,
    [OPCODE_CMP] = 0,
-   [OPCODE_COS] = nir_op_fcos,
+   [OPCODE_COS] = 0,
    [OPCODE_DDX] = nir_op_fddx,
    [OPCODE_DDY] = nir_op_fddy,
    [OPCODE_DP2] = 0,
@@ -706,11 +698,11 @@ static const nir_op op_trans[MAX_OPCODE] = {
    [OPCODE_DPH] = 0,
    [OPCODE_DST] = 0,
    [OPCODE_END] = 0,
-   [OPCODE_EX2] = nir_op_fexp2,
+   [OPCODE_EX2] = 0,
    [OPCODE_EXP] = 0,
    [OPCODE_FLR] = nir_op_ffloor,
    [OPCODE_FRC] = nir_op_ffract,
-   [OPCODE_LG2] = nir_op_flog2,
+   [OPCODE_LG2] = 0,
    [OPCODE_LIT] = 0,
    [OPCODE_LOG] = 0,
    [OPCODE_LRP] = 0,
@@ -719,15 +711,15 @@ static const nir_op op_trans[MAX_OPCODE] = {
    [OPCODE_MIN] = nir_op_fmin,
    [OPCODE_MOV] = nir_op_fmov,
    [OPCODE_MUL] = nir_op_fmul,
-   [OPCODE_POW] = nir_op_fpow,
-   [OPCODE_RCP] = nir_op_frcp,
+   [OPCODE_POW] = 0,
+   [OPCODE_RCP] = 0,
 
-   [OPCODE_RSQ] = nir_op_frsq,
+   [OPCODE_RSQ] = 0,
    [OPCODE_SCS] = 0,
    [OPCODE_SEQ] = 0,
    [OPCODE_SGE] = 0,
    [OPCODE_SGT] = 0,
-   [OPCODE_SIN] = nir_op_fsin,
+   [OPCODE_SIN] = 0,
    [OPCODE_SLE] = 0,
    [OPCODE_SLT] = 0,
    [OPCODE_SNE] = 0,
@@ -740,7 +732,6 @@ static const nir_op op_trans[MAX_OPCODE] = {
    [OPCODE_TXD] = 0,
    [OPCODE_TXL] = 0,
    [OPCODE_TXP] = 0,
-   [OPCODE_TXP_NV] = 0,
    [OPCODE_XPD] = 0,
 };
 
@@ -764,7 +755,8 @@ ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst)
 
    switch (op) {
    case OPCODE_RSQ:
-      ptn_move_dest(b, dest, nir_frsq(b, ptn_channel(b, src[0], X)));
+      ptn_move_dest(b, dest,
+                    nir_frsq(b, nir_fabs(b, ptn_channel(b, src[0], X))));
       break;
 
    case OPCODE_RCP:
@@ -878,7 +870,6 @@ ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst)
    case OPCODE_TXD:
    case OPCODE_TXL:
    case OPCODE_TXP:
-   case OPCODE_TXP_NV:
       ptn_tex(b, dest, src, prog_inst);
       break;
 
@@ -891,7 +882,7 @@ ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst)
       break;
 
    default:
-      if (op_trans[op] != 0 || op == OPCODE_MOV) {
+      if (op_trans[op] != 0) {
          ptn_alu(b, op_trans[op], dest, src);
       } else {
          fprintf(stderr, "unknown opcode: %s\n", _mesa_opcode_string(op));
@@ -900,8 +891,8 @@ ptn_emit_instruction(struct ptn_compile *c, struct prog_instruction *prog_inst)
       break;
    }
 
-   if (prog_inst->SaturateMode) {
-      assert(prog_inst->SaturateMode == SATURATE_ZERO_ONE);
+   if (prog_inst->Saturate) {
+      assert(prog_inst->Saturate);
       assert(!dest.dest.is_ssa);
       ptn_move_dest(b, dest, nir_fsat(b, ptn_src_for_dest(c, &dest)));
    }
@@ -920,14 +911,28 @@ ptn_add_output_stores(struct ptn_compile *c)
 {
    nir_builder *b = &c->build;
 
-   foreach_list_typed(nir_variable, var, node, &b->shader->outputs) {
+   nir_foreach_variable(var, &b->shader->outputs) {
       nir_intrinsic_instr *store =
          nir_intrinsic_instr_create(b->shader, nir_intrinsic_store_var);
-      store->num_components = 4;
+      store->num_components = glsl_get_vector_elements(var->type);
+      nir_intrinsic_set_write_mask(store, (1 << store->num_components) - 1);
       store->variables[0] =
          nir_deref_var_create(store, c->output_vars[var->data.location]);
-      store->src[0].reg.reg = c->output_regs[var->data.location];
-      nir_instr_insert_after_cf_list(c->build.cf_node_list, &store->instr);
+
+      if (c->prog->Target == GL_FRAGMENT_PROGRAM_ARB &&
+          var->data.location == FRAG_RESULT_DEPTH) {
+         /* result.depth has this strange convention of being the .z component of
+          * a vec4 with undefined .xyw components.  We resolve it to a scalar, to
+          * match GLSL's gl_FragDepth and the expectations of most backends.
+          */
+         nir_alu_src alu_src = { NIR_SRC_INIT };
+         alu_src.src = nir_src_for_reg(c->output_regs[FRAG_RESULT_DEPTH]);
+         alu_src.swizzle[0] = SWIZZLE_Z;
+         store->src[0] = nir_src_for_ssa(nir_fmov_alu(b, alu_src, 1));
+      } else {
+         store->src[0].reg.reg = c->output_regs[var->data.location];
+      }
+      nir_builder_instr_insert(b, &store->instr);
    }
 }
 
@@ -942,11 +947,10 @@ setup_registers_and_variables(struct ptn_compile *c)
    for (int i = 0; i < num_inputs; i++) {
       if (!(c->prog->InputsRead & BITFIELD64_BIT(i)))
          continue;
-      nir_variable *var = rzalloc(shader, nir_variable);
-      var->type = glsl_vec4_type();
-      var->data.read_only = true;
-      var->data.mode = nir_var_shader_in;
-      var->name = ralloc_asprintf(var, "in_%d", i);
+
+      nir_variable *var =
+         nir_variable_create(shader, nir_var_shader_in, glsl_vec4_type(),
+                             ralloc_asprintf(shader, "in_%d", i));
       var->data.location = i;
       var->data.index = 0;
 
@@ -971,35 +975,31 @@ setup_registers_and_variables(struct ptn_compile *c)
             load_x->num_components = 1;
             load_x->variables[0] = nir_deref_var_create(load_x, var);
             nir_ssa_dest_init(&load_x->instr, &load_x->dest, 1, NULL);
-            nir_instr_insert_after_cf_list(b->cf_node_list, &load_x->instr);
+            nir_builder_instr_insert(b, &load_x->instr);
 
             nir_ssa_def *f001 = nir_vec4(b, &load_x->dest.ssa, nir_imm_float(b, 0.0),
                                          nir_imm_float(b, 0.0), nir_imm_float(b, 1.0));
 
-            nir_variable *fullvar = rzalloc(shader, nir_variable);
-            fullvar->type = glsl_vec4_type();
-            fullvar->data.mode = nir_var_local;
-            fullvar->name = "fogcoord_tmp";
-            exec_list_push_tail(&b->impl->locals, &fullvar->node);
-
+            nir_variable *fullvar =
+               nir_local_variable_create(b->impl, glsl_vec4_type(),
+                                         "fogcoord_tmp");
             nir_intrinsic_instr *store =
                nir_intrinsic_instr_create(shader, nir_intrinsic_store_var);
             store->num_components = 4;
+            nir_intrinsic_set_write_mask(store, WRITEMASK_XYZW);
             store->variables[0] = nir_deref_var_create(store, fullvar);
             store->src[0] = nir_src_for_ssa(f001);
-            nir_instr_insert_after_cf_list(b->cf_node_list, &store->instr);
+            nir_builder_instr_insert(b, &store->instr);
 
-            /* Insert the real input into the list so the driver has real
-             * inputs, but set c->input_vars[i] to the temporary so we use
+            /* We inserted the real input into the list so the driver has real
+             * inputs, but we set c->input_vars[i] to the temporary so we use
              * the splatted value.
              */
-            exec_list_push_tail(&shader->inputs, &var->node);
             c->input_vars[i] = fullvar;
             continue;
          }
       }
 
-      exec_list_push_tail(&shader->inputs, &var->node);
       c->input_vars[i] = var;
    }
 
@@ -1019,7 +1019,10 @@ setup_registers_and_variables(struct ptn_compile *c)
       reg->num_components = 4;
 
       nir_variable *var = rzalloc(shader, nir_variable);
-      var->type = glsl_vec4_type();
+      if (c->prog->Target == GL_FRAGMENT_PROGRAM_ARB && i == FRAG_RESULT_DEPTH)
+         var->type = glsl_float_type();
+      else
+         var->type = glsl_vec4_type();
       var->data.mode = nir_var_shader_out;
       var->name = ralloc_asprintf(var, "out_%d", i);
 
@@ -1036,7 +1039,7 @@ setup_registers_and_variables(struct ptn_compile *c)
    c->temp_regs = rzalloc_array(c, nir_register *, c->prog->NumTemporaries);
 
    nir_register *reg;
-   for (int i = 0; i < c->prog->NumTemporaries; i++) {
+   for (unsigned i = 0; i < c->prog->NumTemporaries; i++) {
       reg = nir_local_reg_create(b->impl);
       if (!reg) {
          c->error = true;
@@ -1062,30 +1065,25 @@ prog_to_nir(const struct gl_program *prog,
 {
    struct ptn_compile *c;
    struct nir_shader *s;
+   gl_shader_stage stage = _mesa_program_enum_to_shader_stage(prog->Target);
 
    c = rzalloc(NULL, struct ptn_compile);
    if (!c)
       return NULL;
-   s = nir_shader_create(NULL, options);
-   if (!s)
-      goto fail;
    c->prog = prog;
 
-   c->parameters = rzalloc(s, nir_variable);
-   c->parameters->type = glsl_array_type(glsl_vec4_type(),
-                                            prog->Parameters->NumParameters);
-   c->parameters->name = "parameters";
-   c->parameters->data.read_only = true;
-   c->parameters->data.mode = nir_var_uniform;
-   exec_list_push_tail(&s->uniforms, &c->parameters->node);
-
-   nir_function *func = nir_function_create(s, "main");
-   nir_function_overload *overload = nir_function_overload_create(func);
-   nir_function_impl *impl = nir_function_impl_create(overload);
-
-   c->build.shader = s;
-   c->build.impl = impl;
-   c->build.cf_node_list = &impl->body;
+   nir_builder_init_simple_shader(&c->build, NULL, stage, options);
+   s = c->build.shader;
+
+   if (prog->Parameters->NumParameters > 0) {
+      c->parameters = rzalloc(s, nir_variable);
+      c->parameters->type =
+         glsl_array_type(glsl_vec4_type(), prog->Parameters->NumParameters);
+      c->parameters->name = "parameters";
+      c->parameters->data.read_only = true;
+      c->parameters->data.mode = nir_var_uniform;
+      exec_list_push_tail(&s->uniforms, &c->parameters->node);
+   }
 
    setup_registers_and_variables(c);
    if (unlikely(c->error))
@@ -1100,6 +1098,25 @@ prog_to_nir(const struct gl_program *prog,
 
    ptn_add_output_stores(c);
 
+   s->info.name = ralloc_asprintf(s, "ARB%d", prog->Id);
+   s->info.num_textures = _mesa_fls(prog->SamplersUsed);
+   s->info.num_ubos = 0;
+   s->info.num_abos = 0;
+   s->info.num_ssbos = 0;
+   s->info.num_images = 0;
+   s->info.inputs_read = prog->InputsRead;
+   s->info.outputs_written = prog->OutputsWritten;
+   s->info.system_values_read = prog->SystemValuesRead;
+   s->info.uses_texture_gather = false;
+   s->info.uses_clip_distance_out = false;
+   s->info.separate_shader = false;
+
+   if (stage == MESA_SHADER_FRAGMENT) {
+      struct gl_fragment_program *fp = (struct gl_fragment_program *)prog;
+
+      s->info.fs.uses_discard = fp->UsesKill;
+   }
+
 fail:
    if (c->error) {
       ralloc_free(s);