[Mesa-dev] [PATCH v2 5/6] i965/fs: Add ARB_fragment_program support to the NIR backend.
Kenneth Graunke
kenneth at whitecape.org
Wed Mar 25 16:21:10 PDT 2015
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 at whitecape.org>
Reviewed-by: Jordan Justen <jordan.l.justen at intel.com> [v1]
---
src/mesa/drivers/dri/i965/brw_fs.cpp | 16 ++++-----
src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 61 +++++++++++++++++++++++---------
2 files changed, 51 insertions(+), 26 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index a57f501..6969286 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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();
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index 0b8ed1a..21e52fe 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -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];
+ }
+ }
}
}
--
2.3.4
More information about the mesa-dev
mailing list