i965/fs: Add ARB_fragment_program support to the NIR backend.
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>
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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 (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 (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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user