freedreno/ir3: refactor NIR IR handling
authorRob Clark <robclark@freedesktop.org>
Sat, 24 Oct 2015 18:30:31 +0000 (14:30 -0400)
committerRob Clark <robclark@freedesktop.org>
Sun, 3 Jan 2016 14:11:27 +0000 (09:11 -0500)
Immediately convert into NIR and do an initial key-agnostic lowering/
optimization pass.  This should let us share most of the per-variant
transformations between each variant, and hopefully minimize the draw-
time variant creation part of the compilation process.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
src/gallium/drivers/freedreno/Makefile.sources
src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c
src/gallium/drivers/freedreno/ir3/ir3_nir.c [new file with mode: 0644]
src/gallium/drivers/freedreno/ir3/ir3_nir.h
src/gallium/drivers/freedreno/ir3/ir3_shader.c
src/gallium/drivers/freedreno/ir3/ir3_shader.h

index baae9144005507dff91e9390c87ca98221186827..74ef416865510e64862f299f3bd83b0b7ccc1e73 100644 (file)
@@ -128,6 +128,7 @@ ir3_SOURCES := \
        ir3/ir3_group.c \
        ir3/ir3.h \
        ir3/ir3_legalize.c \
+       ir3/ir3_nir.c \
        ir3/ir3_nir.h \
        ir3/ir3_nir_lower_if_else.c \
        ir3/ir3_print.c \
index d55daeefe063bffb7ea3846afff91d988860ac99..481859efb174b939c0fc2bcaabb694a42e784c13 100644 (file)
@@ -40,6 +40,7 @@
 #include "freedreno_util.h"
 
 #include "ir3_compiler.h"
+#include "ir3_nir.h"
 #include "instr-a3xx.h"
 #include "ir3.h"
 
@@ -105,10 +106,10 @@ int main(int argc, char **argv)
        const char *filename;
        struct tgsi_token toks[65536];
        struct tgsi_parse_context parse;
-       struct ir3_compiler *compiler;
        struct ir3_shader_variant v;
        struct ir3_shader s;
        struct ir3_shader_key key = {};
+       /* TODO cmdline option to target different gpus: */
        unsigned gpu_id = 320;
        const char *info;
        void *ptr;
@@ -228,7 +229,12 @@ int main(int argc, char **argv)
        if (!tgsi_text_translate(ptr, toks, Elements(toks)))
                errx(1, "could not parse `%s'", filename);
 
-       s.tokens = toks;
+       if (fd_mesa_debug & FD_DBG_OPTMSGS)
+               tgsi_dump(toks, 0);
+
+       nir_shader *nir = ir3_tgsi_to_nir(toks);
+       s.compiler = ir3_compiler_create(gpu_id);
+       s.nir = ir3_optimize_nir(&s, nir, NULL);
 
        v.key = key;
        v.shader = &s;
@@ -246,11 +252,8 @@ int main(int argc, char **argv)
                break;
        }
 
-       /* TODO cmdline option to target different gpus: */
-       compiler = ir3_compiler_create(gpu_id);
-
        info = "NIR compiler";
-       ret = ir3_compile_shader_nir(compiler, &v);
+       ret = ir3_compile_shader_nir(s.compiler, &v);
        if (ret) {
                fprintf(stderr, "compiler failed!\n");
                return ret;
index bb2221d17d3084fd2c6249871d582bae195554e9..0a25d5252a11b15f5a8f1962e57561479430871a 100644 (file)
 #include "util/u_string.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
-#include "tgsi/tgsi_lowering.h"
-#include "tgsi/tgsi_strings.h"
-
-#include "nir/tgsi_to_nir.h"
 
 #include "freedreno_util.h"
 
@@ -123,97 +119,10 @@ struct ir3_compile {
 static struct ir3_instruction * create_immed(struct ir3_block *block, uint32_t val);
 static struct ir3_block * get_block(struct ir3_compile *ctx, nir_block *nblock);
 
-static struct nir_shader *to_nir(struct ir3_compile *ctx,
-               const struct tgsi_token *tokens, struct ir3_shader_variant *so)
-{
-       static const nir_shader_compiler_options options = {
-                       .lower_fpow = true,
-                       .lower_fsat = true,
-                       .lower_scmp = true,
-                       .lower_flrp = true,
-                       .lower_ffract = true,
-                       .native_integers = true,
-       };
-       struct nir_lower_tex_options tex_options = {
-                       .lower_rect = 0,
-       };
-       bool progress;
-
-       switch (so->type) {
-       case SHADER_FRAGMENT:
-       case SHADER_COMPUTE:
-               tex_options.saturate_s = so->key.fsaturate_s;
-               tex_options.saturate_t = so->key.fsaturate_t;
-               tex_options.saturate_r = so->key.fsaturate_r;
-               break;
-       case SHADER_VERTEX:
-               tex_options.saturate_s = so->key.vsaturate_s;
-               tex_options.saturate_t = so->key.vsaturate_t;
-               tex_options.saturate_r = so->key.vsaturate_r;
-               break;
-       }
-
-       if (ctx->compiler->gpu_id >= 400) {
-               /* a4xx seems to have *no* sam.p */
-               tex_options.lower_txp = ~0;  /* lower all txp */
-       } else {
-               /* a3xx just needs to avoid sam.p for 3d tex */
-               tex_options.lower_txp = (1 << GLSL_SAMPLER_DIM_3D);
-       }
-
-       struct nir_shader *s = tgsi_to_nir(tokens, &options);
-
-       if (fd_mesa_debug & FD_DBG_DISASM) {
-               debug_printf("----------------------\n");
-               nir_print_shader(s, stdout);
-               debug_printf("----------------------\n");
-       }
-
-       nir_opt_global_to_local(s);
-       nir_convert_to_ssa(s);
-       if (s->stage == MESA_SHADER_VERTEX) {
-               nir_lower_clip_vs(s, so->key.ucp_enables);
-       } else if (s->stage == MESA_SHADER_FRAGMENT) {
-               nir_lower_clip_fs(s, so->key.ucp_enables);
-       }
-       nir_lower_tex(s, &tex_options);
-       if (so->key.color_two_side)
-               nir_lower_two_sided_color(s);
-       nir_lower_idiv(s);
-       nir_lower_load_const_to_scalar(s);
-
-       do {
-               progress = false;
-
-               nir_lower_vars_to_ssa(s);
-               nir_lower_alu_to_scalar(s);
-               nir_lower_phis_to_scalar(s);
-
-               progress |= nir_copy_prop(s);
-               progress |= nir_opt_dce(s);
-               progress |= nir_opt_cse(s);
-               progress |= ir3_nir_lower_if_else(s);
-               progress |= nir_opt_algebraic(s);
-               progress |= nir_opt_constant_folding(s);
-
-       } while (progress);
-
-       nir_remove_dead_variables(s);
-       nir_validate_shader(s);
-
-       if (fd_mesa_debug & FD_DBG_DISASM) {
-               debug_printf("----------------------\n");
-               nir_print_shader(s, stdout);
-               debug_printf("----------------------\n");
-       }
-
-       return s;
-}
 
 static struct ir3_compile *
 compile_init(struct ir3_compiler *compiler,
-               struct ir3_shader_variant *so,
-               const struct tgsi_token *tokens)
+               struct ir3_shader_variant *so)
 {
        struct ir3_compile *ctx = rzalloc(NULL, struct ir3_compile);
 
@@ -239,7 +148,28 @@ compile_init(struct ir3_compiler *compiler,
        ctx->block_ht = _mesa_hash_table_create(ctx,
                        _mesa_hash_pointer, _mesa_key_pointer_equal);
 
-       ctx->s = to_nir(ctx, tokens, so);
+       /* TODO: maybe generate some sort of bitmask of what key
+        * lowers vs what shader has (ie. no need to lower
+        * texture clamp lowering if no texture sample instrs)..
+        * although should be done further up the stack to avoid
+        * creating duplicate variants..
+        */
+
+       if (ir3_key_lowers_nir(&so->key)) {
+               nir_shader *s = nir_shader_clone(ctx, so->shader->nir);
+               ctx->s = ir3_optimize_nir(so->shader, s, &so->key);
+       } else {
+               /* fast-path for shader key that lowers nothing in NIR: */
+               ctx->s = so->shader->nir;
+       }
+
+       if (fd_mesa_debug & FD_DBG_DISASM) {
+               DBG("dump nir%dv%d: type=%d, k={bp=%u,cts=%u,hp=%u}",
+                       so->shader->id, so->id, so->type,
+                       so->key.binning_pass, so->key.color_two_side,
+                       so->key.half_precision);
+               nir_print_shader(ctx->s, stdout);
+       }
 
        so->first_driver_param = so->first_immediate = ctx->s->num_uniforms;
 
@@ -2497,7 +2427,7 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler,
 
        assert(!so->ir);
 
-       ctx = compile_init(compiler, so, so->shader->tokens);
+       ctx = compile_init(compiler, so);
        if (!ctx) {
                DBG("INIT failed!");
                ret = -1;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_nir.c
new file mode 100644 (file)
index 0000000..4d83ee6
--- /dev/null
@@ -0,0 +1,144 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2015 Rob Clark <robclark@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Rob Clark <robclark@freedesktop.org>
+ */
+
+
+#include "freedreno_util.h"
+
+#include "ir3_nir.h"
+#include "ir3_compiler.h"
+#include "ir3_shader.h"
+
+#include "nir/tgsi_to_nir.h"
+
+struct nir_shader *
+ir3_tgsi_to_nir(const struct tgsi_token *tokens)
+{
+       static const nir_shader_compiler_options options = {
+                       .lower_fpow = true,
+                       .lower_fsat = true,
+                       .lower_scmp = true,
+                       .lower_flrp = true,
+                       .lower_ffract = true,
+                       .native_integers = true,
+       };
+       return tgsi_to_nir(tokens, &options);
+}
+
+/* for given shader key, are any steps handled in nir? */
+bool
+ir3_key_lowers_nir(const struct ir3_shader_key *key)
+{
+       return key->fsaturate_s | key->fsaturate_t | key->fsaturate_r |
+                       key->vsaturate_s | key->vsaturate_t | key->vsaturate_r |
+                       key->ucp_enables | key->color_two_side;
+}
+
+struct nir_shader *
+ir3_optimize_nir(struct ir3_shader *shader, nir_shader *s,
+               const struct ir3_shader_key *key)
+{
+       struct nir_lower_tex_options tex_options = {
+                       .lower_rect = 0,
+       };
+       bool progress;
+
+       if (key) {
+               switch (shader->type) {
+               case SHADER_FRAGMENT:
+               case SHADER_COMPUTE:
+                       tex_options.saturate_s = key->fsaturate_s;
+                       tex_options.saturate_t = key->fsaturate_t;
+                       tex_options.saturate_r = key->fsaturate_r;
+                       break;
+               case SHADER_VERTEX:
+                       tex_options.saturate_s = key->vsaturate_s;
+                       tex_options.saturate_t = key->vsaturate_t;
+                       tex_options.saturate_r = key->vsaturate_r;
+                       break;
+               }
+       }
+
+       if (shader->compiler->gpu_id >= 400) {
+               /* a4xx seems to have *no* sam.p */
+               tex_options.lower_txp = ~0;  /* lower all txp */
+       } else {
+               /* a3xx just needs to avoid sam.p for 3d tex */
+               tex_options.lower_txp = (1 << GLSL_SAMPLER_DIM_3D);
+       }
+
+       if (fd_mesa_debug & FD_DBG_DISASM) {
+               debug_printf("----------------------\n");
+               nir_print_shader(s, stdout);
+               debug_printf("----------------------\n");
+       }
+
+       nir_opt_global_to_local(s);
+       nir_convert_to_ssa(s);
+       if (key) {
+               if (s->stage == MESA_SHADER_VERTEX) {
+                       nir_lower_clip_vs(s, key->ucp_enables);
+               } else if (s->stage == MESA_SHADER_FRAGMENT) {
+                       nir_lower_clip_fs(s, key->ucp_enables);
+               }
+               if (key->color_two_side) {
+                       nir_lower_two_sided_color(s);
+               }
+       }
+       nir_lower_tex(s, &tex_options);
+       nir_lower_idiv(s);
+       nir_lower_load_const_to_scalar(s);
+
+       do {
+               progress = false;
+
+               nir_lower_vars_to_ssa(s);
+               nir_lower_alu_to_scalar(s);
+               nir_lower_phis_to_scalar(s);
+
+               progress |= nir_copy_prop(s);
+               progress |= nir_opt_dce(s);
+               progress |= nir_opt_cse(s);
+               progress |= ir3_nir_lower_if_else(s);
+               progress |= nir_opt_algebraic(s);
+               progress |= nir_opt_constant_folding(s);
+
+       } while (progress);
+
+       nir_remove_dead_variables(s);
+       nir_validate_shader(s);
+
+       if (fd_mesa_debug & FD_DBG_DISASM) {
+               debug_printf("----------------------\n");
+               nir_print_shader(s, stdout);
+               debug_printf("----------------------\n");
+       }
+
+       nir_sweep(s);
+
+       return s;
+}
index 9950782dc380d0ba84770fa18682f228c730d955..534199d3744b86452fc2b7c5ce643c7fd6137e76 100644 (file)
 #include "glsl/nir/nir.h"
 #include "glsl/nir/shader_enums.h"
 
+#include "ir3_shader.h"
+
 bool ir3_nir_lower_if_else(nir_shader *shader);
 
+struct nir_shader * ir3_tgsi_to_nir(const struct tgsi_token *tokens);
+bool ir3_key_lowers_nir(const struct ir3_shader_key *key);
+struct nir_shader * ir3_optimize_nir(struct ir3_shader *shader, nir_shader *s,
+               const struct ir3_shader_key *key);
+
 #endif /* IR3_NIR_H_ */
index 7b5653322560c7f42589baeb6bcabd555974f96d..7d17f426ad352553417e007d68ae69e9ca06cb2e 100644 (file)
@@ -39,7 +39,7 @@
 
 #include "ir3_shader.h"
 #include "ir3_compiler.h"
-
+#include "ir3_nir.h"
 
 static void
 delete_variant(struct ir3_shader_variant *v)
@@ -187,12 +187,6 @@ create_variant(struct ir3_shader *shader, struct ir3_shader_key key)
        v->key = key;
        v->type = shader->type;
 
-       if (fd_mesa_debug & FD_DBG_DISASM) {
-               DBG("dump tgsi: type=%d, k={bp=%u,cts=%u,hp=%u}", shader->type,
-                       key.binning_pass, key.color_two_side, key.half_precision);
-               tgsi_dump(shader->tokens, 0);
-       }
-
        ret = ir3_compile_shader_nir(shader->compiler, v);
        if (ret) {
                debug_error("compile failed!");
@@ -267,7 +261,7 @@ ir3_shader_destroy(struct ir3_shader *shader)
                v = v->next;
                delete_variant(t);
        }
-       free((void *)shader->tokens);
+       ralloc_free(shader->nir);
        free(shader);
 }
 
@@ -281,14 +275,24 @@ ir3_shader_create(struct pipe_context *pctx,
        shader->id = ++shader->compiler->shader_count;
        shader->pctx = pctx;
        shader->type = type;
-       shader->tokens = tgsi_dup_tokens(cso->tokens);
+       if (fd_mesa_debug & FD_DBG_DISASM) {
+               DBG("dump tgsi: type=%d", shader->type);
+               tgsi_dump(cso->tokens, 0);
+       }
+       nir_shader *nir = ir3_tgsi_to_nir(cso->tokens);
+       /* do first pass optimization, ignoring the key: */
+       shader->nir = ir3_optimize_nir(shader, nir, NULL);
+       if (fd_mesa_debug & FD_DBG_DISASM) {
+               DBG("dump nir%d: type=%d", shader->id, shader->type);
+               nir_print_shader(shader->nir, stdout);
+       }
        shader->stream_output = cso->stream_output;
        if (fd_mesa_debug & FD_DBG_SHADERDB) {
                /* if shader-db run, create a standard variant immediately
                 * (as otherwise nothing will trigger the shader to be
                 * actually compiled)
                 */
-               static struct ir3_shader_key key = {};
+               static struct ir3_shader_key key = {0};
                ir3_shader_variant(shader, key);
        }
        return shader;
index cf99a4c05edb288b50377b7dc24c231612f28fdc..b3c28a41387596ad8fd1c42ccf217408a6d27833 100644 (file)
@@ -230,6 +230,8 @@ struct ir3_shader_variant {
        struct ir3_shader *shader;
 };
 
+typedef struct nir_shader nir_shader;
+
 struct ir3_shader {
        enum shader_t type;
 
@@ -240,7 +242,7 @@ struct ir3_shader {
        struct ir3_compiler *compiler;
 
        struct pipe_context *pctx;    /* TODO replace w/ pipe_screen */
-       const struct tgsi_token *tokens;
+       nir_shader *nir;
        struct pipe_stream_output_info stream_output;
 
        struct ir3_shader_variant *variants;