From: Rob Clark Date: Sat, 24 Oct 2015 18:30:31 +0000 (-0400) Subject: freedreno/ir3: refactor NIR IR handling X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=74135f804a4f18040a0a62664df67d35c8090d1d;p=mesa.git freedreno/ir3: refactor NIR IR handling 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 --- diff --git a/src/gallium/drivers/freedreno/Makefile.sources b/src/gallium/drivers/freedreno/Makefile.sources index baae9144005..74ef4168655 100644 --- a/src/gallium/drivers/freedreno/Makefile.sources +++ b/src/gallium/drivers/freedreno/Makefile.sources @@ -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 \ diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c index d55daeefe06..481859efb17 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c @@ -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; diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c index bb2221d17d3..0a25d5252a1 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler_nir.c @@ -32,10 +32,6 @@ #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 index 00000000000..4d83ee6a987 --- /dev/null +++ b/src/gallium/drivers/freedreno/ir3/ir3_nir.c @@ -0,0 +1,144 @@ +/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ + +/* + * Copyright (C) 2015 Rob Clark + * + * 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 + */ + + +#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; +} diff --git a/src/gallium/drivers/freedreno/ir3/ir3_nir.h b/src/gallium/drivers/freedreno/ir3/ir3_nir.h index 9950782dc38..534199d3744 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_nir.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_nir.h @@ -32,6 +32,13 @@ #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_ */ diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index 7b565332256..7d17f426ad3 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -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; diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.h b/src/gallium/drivers/freedreno/ir3/ir3_shader.h index cf99a4c05ed..b3c28a41387 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.h @@ -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;