summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/nir
diff options
context:
space:
mode:
authorTimur Kristóf <[email protected]>2019-03-05 18:59:47 +0100
committerEric Anholt <[email protected]>2019-03-05 19:13:27 +0000
commit9a834447d652ea50864bb6c32f4ff99ac10d39bf (patch)
treeb60582e7bb504b2e2bad847f6494b418db9e83ea /src/gallium/auxiliary/nir
parente582e761b7f49d1c0b100289b62442e6295cefef (diff)
tgsi_to_nir: Produce optimized NIR for a given pipe_screen.
With this patch, tgsi_to_nir will output NIR that is tailored to the given pipe, by reading its capabilities and adjusting the NIR code to those capabilities similarly to how glsl_to_nir works. It also adds an optimization loop that brings the output NIR in line with what glsl_to_nir outputs. This is necessary for the same reason why glsl_to_nir has its own optimization loop: currently not every driver does these optimizations yet. For uses which cannot pass a pipe_screen we also keep a variant called tgsi_to_nir_noscreen which keeps the old behavior. Signed-Off-By: Timur Kristóf <[email protected]> Tested-by: Andre Heider <[email protected]> Tested-by: Rob Clark <[email protected]> Acked-By: Eric Anholt <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/nir')
-rw-r--r--src/gallium/auxiliary/nir/tgsi_to_nir.c132
-rw-r--r--src/gallium/auxiliary/nir/tgsi_to_nir.h7
2 files changed, 135 insertions, 4 deletions
diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.c b/src/gallium/auxiliary/nir/tgsi_to_nir.c
index 1260752f0f6..11c16d43615 100644
--- a/src/gallium/auxiliary/nir/tgsi_to_nir.c
+++ b/src/gallium/auxiliary/nir/tgsi_to_nir.c
@@ -23,9 +23,12 @@
*/
#include "util/ralloc.h"
+#include "pipe/p_screen.h"
+
#include "compiler/nir/nir.h"
#include "compiler/nir/nir_control_flow.h"
#include "compiler/nir/nir_builder.h"
+#include "compiler/glsl/gl_nir.h"
#include "compiler/glsl/list.h"
#include "compiler/shader_enums.h"
@@ -91,6 +94,12 @@ struct ttn_compile {
/* How many TGSI_FILE_IMMEDIATE vec4s have been parsed so far. */
unsigned next_imm;
+
+ bool cap_scalar;
+ bool cap_face_is_sysval;
+ bool cap_position_is_sysval;
+ bool cap_packed_uniforms;
+ bool cap_samplers_as_deref;
};
#define ttn_swizzle(b, src, x, y, z, w) \
@@ -1813,28 +1822,54 @@ ttn_parse_tgsi(struct ttn_compile *c, const void *tgsi_tokens)
tgsi_parse_free(&parser);
}
+static void
+ttn_read_pipe_caps(struct ttn_compile *c,
+ struct pipe_screen *screen)
+{
+ c->cap_scalar = screen->get_shader_param(screen, c->scan->processor, PIPE_SHADER_CAP_SCALAR_ISA);
+ c->cap_packed_uniforms = screen->get_param(screen, PIPE_CAP_PACKED_UNIFORMS);
+ c->cap_samplers_as_deref = screen->get_param(screen, PIPE_CAP_NIR_SAMPLERS_AS_DEREF);
+ c->cap_face_is_sysval = screen->get_param(screen, PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL);
+ c->cap_position_is_sysval = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL);
+}
+
/**
* Initializes a TGSI-to-NIR compiler.
*/
static struct ttn_compile *
ttn_compile_init(const void *tgsi_tokens,
- const nir_shader_compiler_options *options)
+ const nir_shader_compiler_options *options,
+ struct pipe_screen *screen)
{
struct ttn_compile *c;
struct nir_shader *s;
struct tgsi_shader_info scan;
+ assert(options || screen);
c = rzalloc(NULL, struct ttn_compile);
tgsi_scan_shader(tgsi_tokens, &scan);
c->scan = &scan;
+ if (!options) {
+ options =
+ screen->get_compiler_options(screen, PIPE_SHADER_IR_NIR, scan.processor);
+ }
+
nir_builder_init_simple_shader(&c->build, NULL,
tgsi_processor_to_shader_stage(scan.processor),
options);
s = c->build.shader;
+ if (screen) {
+ ttn_read_pipe_caps(c, screen);
+ } else {
+ /* TTN used to be hard coded to always make FACE a sysval,
+ * so it makes sense to preserve that behavior so users don't break. */
+ c->cap_face_is_sysval = true;
+ }
+
if (s->info.stage == MESA_SHADER_FRAGMENT)
s->info.fs.untyped_color_outputs = true;
@@ -1872,14 +1907,105 @@ ttn_compile_init(const void *tgsi_tokens,
return c;
}
+static void
+ttn_optimize_nir(nir_shader *nir, bool scalar)
+{
+ bool progress;
+ do {
+ progress = false;
+
+ NIR_PASS_V(nir, nir_lower_vars_to_ssa);
+
+ if (scalar) {
+ NIR_PASS_V(nir, nir_lower_alu_to_scalar);
+ NIR_PASS_V(nir, nir_lower_phis_to_scalar);
+ }
+
+ NIR_PASS_V(nir, nir_lower_alu);
+ NIR_PASS_V(nir, nir_lower_pack);
+ NIR_PASS(progress, nir, nir_copy_prop);
+ NIR_PASS(progress, nir, nir_opt_remove_phis);
+ NIR_PASS(progress, nir, nir_opt_dce);
+
+ if (nir_opt_trivial_continues(nir)) {
+ progress = true;
+ NIR_PASS(progress, nir, nir_copy_prop);
+ NIR_PASS(progress, nir, nir_opt_dce);
+ }
+
+ NIR_PASS(progress, nir, nir_opt_if);
+ NIR_PASS(progress, nir, nir_opt_dead_cf);
+ NIR_PASS(progress, nir, nir_opt_cse);
+ NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true);
+
+ NIR_PASS(progress, nir, nir_opt_algebraic);
+ NIR_PASS(progress, nir, nir_opt_constant_folding);
+
+ NIR_PASS(progress, nir, nir_opt_undef);
+ NIR_PASS(progress, nir, nir_opt_conditional_discard);
+
+ if (nir->options->max_unroll_iterations) {
+ NIR_PASS(progress, nir, nir_opt_loop_unroll, (nir_variable_mode)0);
+ }
+
+ } while (progress);
+
+}
+
+/**
+ * Finalizes the NIR in a similar way as st_glsl_to_nir does.
+ *
+ * Drivers expect that these passes are already performed,
+ * so we have to do it here too.
+ */
+static void
+ttn_finalize_nir(struct ttn_compile *c)
+{
+ struct nir_shader *nir = c->build.shader;
+
+ NIR_PASS_V(nir, nir_lower_vars_to_ssa);
+ NIR_PASS_V(nir, nir_lower_regs_to_ssa);
+
+ NIR_PASS_V(nir, nir_lower_global_vars_to_local);
+ NIR_PASS_V(nir, nir_split_var_copies);
+ NIR_PASS_V(nir, nir_lower_var_copies);
+
+ if (c->cap_packed_uniforms)
+ NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, 16);
+
+ if (c->cap_samplers_as_deref)
+ NIR_PASS_V(nir, gl_nir_lower_samplers_as_deref, NULL);
+ else
+ NIR_PASS_V(nir, gl_nir_lower_samplers, NULL);
+
+ ttn_optimize_nir(nir, c->cap_scalar);
+ nir_shader_gather_info(nir, c->build.impl);
+ nir_validate_shader(nir, "TTN: after all optimizations");
+}
+
struct nir_shader *
tgsi_to_nir(const void *tgsi_tokens,
- const nir_shader_compiler_options *options)
+ struct pipe_screen *screen)
+{
+ struct ttn_compile *c;
+ struct nir_shader *s;
+
+ c = ttn_compile_init(tgsi_tokens, NULL, screen);
+ s = c->build.shader;
+ ttn_finalize_nir(c);
+ ralloc_free(c);
+
+ return s;
+}
+
+struct nir_shader *
+tgsi_to_nir_noscreen(const void *tgsi_tokens,
+ const nir_shader_compiler_options *options)
{
struct ttn_compile *c;
struct nir_shader *s;
- c = ttn_compile_init(tgsi_tokens, options);
+ c = ttn_compile_init(tgsi_tokens, options, NULL);
s = c->build.shader;
ralloc_free(c);
diff --git a/src/gallium/auxiliary/nir/tgsi_to_nir.h b/src/gallium/auxiliary/nir/tgsi_to_nir.h
index a7060bca610..551ee917c8a 100644
--- a/src/gallium/auxiliary/nir/tgsi_to_nir.h
+++ b/src/gallium/auxiliary/nir/tgsi_to_nir.h
@@ -22,7 +22,12 @@
*/
#include "compiler/nir/nir.h"
+#include "pipe/p_screen.h"
struct nir_shader *
tgsi_to_nir(const void *tgsi_tokens,
- const struct nir_shader_compiler_options *options);
+ struct pipe_screen *screen);
+
+struct nir_shader *
+tgsi_to_nir_noscreen(const void *tgsi_tokens,
+ const nir_shader_compiler_options *options);