i965/fs: Add ARB_fragment_program support to the NIR backend.
authorKenneth Graunke <kenneth@whitecape.org>
Fri, 30 Jan 2015 09:16:49 +0000 (01:16 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Sat, 28 Mar 2015 04:16:34 +0000 (21:16 -0700)
Use prog_to_nir where we would normally call glsl_to_nir, handle program
parameter lists, and skip a few things that don't exist.

Using NIR generates much better shader code than Mesa IR, since we get
real optimizations, as opposed to prog_optimize:

total instructions in shared programs: 314007 -> 279892 (-10.86%)
instructions in affected programs:     285173 -> 251058 (-11.96%)
helped:                                2001
HURT:                                  67
GAINED:                                4
LOST:                                  7

v2: Change early return in nir_setup_uniforms to if/else (Jordan).

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs_nir.cpp

index a57f501a37e2b1ed17a62ed37e96ba7e9482ef16..69692863bb9b9dd3f3aa950392b0bb26ee8bb479 100644 (file)
@@ -3954,15 +3954,13 @@ fs_visitor::run_fs()
       /* Generate FS IR for main().  (the visitor only descends into
        * functions called "main").
        */
-      if (shader) {
-         if (env_var_as_boolean("INTEL_USE_NIR", false)) {
-            emit_nir_code();
-         } else {
-            foreach_in_list(ir_instruction, ir, shader->base.ir) {
-               base_ir = ir;
-               this->result = reg_undef;
-               ir->accept(this);
-            }
+      if (env_var_as_boolean("INTEL_USE_NIR", false)) {
+         emit_nir_code();
+      } else if (shader) {
+         foreach_in_list(ir_instruction, ir, shader->base.ir) {
+            base_ir = ir;
+            this->result = reg_undef;
+            ir->accept(this);
          }
       } else {
          emit_fragment_program_code();
index 0b8ed1a8b839b718ca0686f907ceef5ddf864e5a..21e52fe0e457d4802dcecfd8807ec66858d04ca2 100644 (file)
@@ -24,6 +24,7 @@
 #include "glsl/ir.h"
 #include "glsl/ir_optimization.h"
 #include "glsl/nir/glsl_to_nir.h"
+#include "program/prog_to_nir.h"
 #include "brw_fs.h"
 #include "brw_nir.h"
 
@@ -86,9 +87,15 @@ fs_visitor::emit_nir_code()
    const nir_shader_compiler_options *options =
       ctx->Const.ShaderCompilerOptions[stage].NirOptions;
 
-   /* first, lower the GLSL IR shader to NIR */
-   lower_output_reads(shader->base.ir);
-   nir_shader *nir = glsl_to_nir(&shader->base, options);
+   nir_shader *nir;
+   /* First, lower the GLSL IR or Mesa IR to NIR */
+   if (shader_prog) {
+      lower_output_reads(shader->base.ir);
+      nir = glsl_to_nir(&shader->base, options);
+   } else {
+      nir = prog_to_nir(prog, options);
+      nir_convert_to_ssa(nir); /* turn registers into SSA */
+   }
    nir_validate_shader(nir);
 
    nir_lower_global_vars_to_local(nir);
@@ -106,9 +113,18 @@ fs_visitor::emit_nir_code()
    /* Get rid of split copies */
    nir_optimize(nir);
 
-   nir_assign_var_locations_scalar_direct_first(nir, &nir->uniforms,
-                                                &num_direct_uniforms,
-                                                &nir->num_uniforms);
+   if (shader_prog) {
+      nir_assign_var_locations_scalar_direct_first(nir, &nir->uniforms,
+                                                   &num_direct_uniforms,
+                                                   &nir->num_uniforms);
+   } else {
+      /* ARB programs generally create a giant array of "uniform" data, and allow
+       * indirect addressing without any boundaries.  In the absence of bounds
+       * analysis, it's all or nothing.  num_direct_uniforms is only useful when
+       * we have some direct and some indirect access; it doesn't matter here.
+       */
+      num_direct_uniforms = 0;
+   }
    nir_assign_var_locations_scalar(&nir->inputs, &nir->num_inputs);
    nir_assign_var_locations_scalar(&nir->outputs, &nir->num_outputs);
 
@@ -118,8 +134,10 @@ fs_visitor::emit_nir_code()
    nir_remove_dead_variables(nir);
    nir_validate_shader(nir);
 
-   nir_lower_samplers(nir, shader_prog, shader->base.Program);
-   nir_validate_shader(nir);
+   if (shader_prog) {
+      nir_lower_samplers(nir, shader_prog, shader->base.Program);
+      nir_validate_shader(nir);
+   }
 
    nir_lower_system_values(nir);
    nir_validate_shader(nir);
@@ -320,16 +338,25 @@ fs_visitor::nir_setup_uniforms(nir_shader *shader)
    if (dispatch_width != 8)
       return;
 
-   foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
-      /* UBO's and atomics don't take up space in the uniform file */
-
-      if (var->interface_type != NULL || var->type->contains_atomic())
-         continue;
+   if (shader_prog) {
+      foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
+         /* UBO's and atomics don't take up space in the uniform file */
+         if (var->interface_type != NULL || var->type->contains_atomic())
+            continue;
 
-      if (strncmp(var->name, "gl_", 3) == 0)
-         nir_setup_builtin_uniform(var);
-      else
-         nir_setup_uniform(var);
+         if (strncmp(var->name, "gl_", 3) == 0)
+            nir_setup_builtin_uniform(var);
+         else
+            nir_setup_uniform(var);
+      }
+   } else {
+      /* prog_to_nir doesn't create uniform variables; set param up directly. */
+      for (unsigned p = 0; p < prog->Parameters->NumParameters; p++) {
+         for (unsigned int i = 0; i < 4; i++) {
+            stage_prog_data->param[4 * p + i] =
+               &prog->Parameters->ParameterValues[p][i];
+         }
+      }
    }
 }