i965/fs_nir: Handle sample ID, position, and mask better
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 17 Dec 2014 20:34:27 +0000 (12:34 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Thu, 15 Jan 2015 15:20:22 +0000 (07:20 -0800)
Before, we were emitting the full pile of setup instructions for sample_id
and sample_pos every time they were used.  With this commit, we emit them
in their own pass once at the beginning of the shader and simply emit uses
later on.  When it comes time for setting up VS, we can put setup for its
special values in the same pass.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_nir.cpp

index ad3d9866d53f9537087e33f6d431dba106ff43d8..2aa58ebf0cb0fb65f385fc147a71fab18558c28b 100644 (file)
@@ -574,6 +574,7 @@ public:
    void nir_setup_uniforms(nir_shader *shader);
    void nir_setup_uniform(nir_variable *var);
    void nir_setup_builtin_uniform(nir_variable *var);
+   void nir_emit_system_values(nir_shader *shader);
    void nir_emit_impl(nir_function_impl *impl);
    void nir_emit_cf_list(exec_list *list);
    void nir_emit_if(nir_if *if_stmt);
@@ -701,6 +702,7 @@ public:
    fs_reg nir_inputs;
    fs_reg nir_outputs;
    fs_reg nir_uniforms;
+   fs_reg *nir_system_values;
 
    /** @{ debug annotation info */
    const char *current_annotation;
index 4c08cfdb6ade9526dfb7f4b48e7b3e8c90b6e4b1..ee2f80e7f355c24c4820783f87a46a36008313f5 100644 (file)
@@ -106,6 +106,8 @@ fs_visitor::emit_nir_code()
       nir_setup_uniforms(nir);
    }
 
+   nir_emit_system_values(nir);
+
    nir_globals = ralloc_array(mem_ctx, fs_reg, nir->reg_alloc);
    foreach_list_typed(nir_register, reg, node, &nir->registers) {
       unsigned array_elems =
@@ -289,6 +291,60 @@ fs_visitor::nir_setup_builtin_uniform(nir_variable *var)
    }
 }
 
+static bool
+emit_system_values_block(nir_block *block, void *void_visitor)
+{
+   fs_visitor *v = (fs_visitor *)void_visitor;
+   fs_reg *reg;
+
+   nir_foreach_instr(block, instr) {
+      if (instr->type != nir_instr_type_intrinsic)
+         continue;
+
+      nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+      switch (intrin->intrinsic) {
+      case nir_intrinsic_load_sample_pos:
+         assert(v->stage == MESA_SHADER_FRAGMENT);
+         reg = &v->nir_system_values[SYSTEM_VALUE_SAMPLE_POS];
+         if (reg->file == BAD_FILE)
+            *reg = *v->emit_samplepos_setup();
+         break;
+
+      case nir_intrinsic_load_sample_id:
+         assert(v->stage == MESA_SHADER_FRAGMENT);
+         reg = &v->nir_system_values[SYSTEM_VALUE_SAMPLE_ID];
+         if (reg->file == BAD_FILE)
+            *reg = *v->emit_sampleid_setup();
+         break;
+
+      case nir_intrinsic_load_sample_mask_in:
+         assert(v->stage == MESA_SHADER_FRAGMENT);
+         assert(v->brw->gen >= 7);
+         reg = &v->nir_system_values[SYSTEM_VALUE_SAMPLE_MASK_IN];
+         if (reg->file == BAD_FILE)
+            *reg = fs_reg(retype(brw_vec8_grf(v->payload.sample_mask_in_reg, 0),
+                                 BRW_REGISTER_TYPE_D));
+         break;
+
+      default:
+         break;
+      }
+   }
+
+   return true;
+}
+
+void
+fs_visitor::nir_emit_system_values(nir_shader *shader)
+{
+   nir_system_values = ralloc_array(mem_ctx, fs_reg, SYSTEM_VALUE_MAX);
+   nir_foreach_overload(shader, overload) {
+      assert(strcmp(overload->function->name, "main") == 0);
+      assert(overload->impl);
+      nir_foreach_block(overload->impl, emit_system_values_block, this);
+   }
+}
+
 void
 fs_visitor::nir_emit_impl(nir_function_impl *impl)
 {
@@ -1276,26 +1332,27 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
       assert(!"TODO");
 
    case nir_intrinsic_load_sample_mask_in: {
-      assert(brw->gen >= 7);
-      fs_reg reg = fs_reg(retype(brw_vec8_grf(payload.sample_mask_in_reg, 0),
-                          BRW_REGISTER_TYPE_D));
-      dest.type = reg.type;
-      emit(MOV(dest, reg));
+      fs_reg sample_mask_in = nir_system_values[SYSTEM_VALUE_SAMPLE_MASK_IN];
+      assert(sample_mask_in.file != BAD_FILE);
+      dest.type = sample_mask_in.type;
+      emit(MOV(dest, sample_mask_in));
       break;
    }
 
    case nir_intrinsic_load_sample_pos: {
-      fs_reg *reg = emit_samplepos_setup();
-      dest.type = reg->type;
-      emit(MOV(dest, *reg));
-      emit(MOV(offset(dest, 1), offset(*reg, 1)));
+      fs_reg sample_pos = nir_system_values[SYSTEM_VALUE_SAMPLE_POS];
+      assert(sample_pos.file != BAD_FILE);
+      dest.type = sample_pos.type;
+      emit(MOV(dest, sample_pos));
+      emit(MOV(offset(dest, 1), offset(sample_pos, 1)));
       break;
    }
 
    case nir_intrinsic_load_sample_id: {
-      fs_reg *reg = emit_sampleid_setup();
-      dest.type = reg->type;
-      emit(MOV(dest, *reg));
+      fs_reg sample_id = nir_system_values[SYSTEM_VALUE_SAMPLE_ID];
+      assert(sample_id.file != BAD_FILE);
+      dest.type = sample_id.type;
+      emit(MOV(dest, sample_id));
       break;
    }